From e760818007f35932ba713faf56a23c0af947f96a Mon Sep 17 00:00:00 2001 From: Jaidyn Ann Date: Wed, 14 Jul 2021 13:17:00 -0500 Subject: [PATCH] (librunview) Init new RenderView/RunView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base-level replacement of the Vision-derived text RunView― a couple important features supported by the replacee haven't been implemented yet, including: * Right-click menu * URL-highlighting/selection * Emote support --- application/views/RenderView.cpp | 120 +- application/views/RenderView.h | 55 +- libs/librunview/Emoconfig.cpp | 1 - libs/librunview/Makefile | 3 - libs/librunview/NormalTextRender.h | 46 - libs/librunview/RunView.cpp | 2372 +--------------------------- libs/librunview/RunView.h | 191 +-- libs/librunview/SmileTextRender.h | 54 - libs/librunview/TextRender.h | 19 - libs/librunview/Theme.cpp | 279 ---- libs/librunview/Theme.h | 125 -- 11 files changed, 78 insertions(+), 3187 deletions(-) delete mode 100644 libs/librunview/NormalTextRender.h delete mode 100644 libs/librunview/SmileTextRender.h delete mode 100644 libs/librunview/TextRender.h delete mode 100644 libs/librunview/Theme.cpp delete mode 100644 libs/librunview/Theme.h diff --git a/application/views/RenderView.cpp b/application/views/RenderView.cpp index 538e31a..1d93914 100644 --- a/application/views/RenderView.cpp +++ b/application/views/RenderView.cpp @@ -1,116 +1,54 @@ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ + #include "RenderView.h" -#include -#include - -#include "AppPreferences.h" +#include -RenderView::RenderView(const char *name, const char* smileyConfig) +RenderView::RenderView(const char* name) : - RunView(BRect(0, 0, 1, 1), name, - fTheme = new Theme(name, COL_MAX_COLORS + 1, COL_MAX_COLORS + 1, - MAX_RENDERS + 1), - B_FOLLOW_ALL, B_WILL_DRAW) + RunView(name) { - if (smileyConfig) - Emoticor::Get()->LoadConfig(smileyConfig); - - PrepareTheme(fTheme); - - SetTimeStampFormat("[%H:%M]"); - if ( IsHidden() ) - Show(); - ScrollToBottom(); } void RenderView::AppendMessage(const char* nick, const char* message, - rgb_color nameColor, time_t time) + rgb_color nameColor, time_t time) { - rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color fg = ui_color(B_PANEL_TEXT_COLOR); + if (BString(message).IsEmpty() == true) return; - Append("<", nameColor, bg, nameColor, time); - Append(nick, fg, bg, fg); - Append("> ", nameColor, bg, nameColor); - if (Emoticor::Get()->Config() == NULL) - Append(message, fg, bg, fg); - else - AddEmoticText(message, fg, bg); - Append("\n", fg, bg, fg); - ScrollToSelection(); + AppendTimestamp(time); + Append("<", nameColor); + Append(nick); + Append("> ", nameColor); + Append(message); + + if (BString(message).EndsWith("\n") == false) Append("\n"); } void RenderView::AppendGenericMessage(const char* message) { - rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color fg = ui_color(B_PANEL_TEXT_COLOR); - - Append(message, fg, bg, fg, time(NULL)); - ScrollToSelection(); + if (BString(message).IsEmpty() == true) return; + AppendTimestamp(time(NULL)); + Append(message, ui_color(B_PANEL_TEXT_COLOR), B_BOLD_FACE); + if (BString(message).EndsWith("\n") == false) Append("\n"); } void -RenderView::AddEmoticText(const char * txt, rgb_color fore, rgb_color bg) +RenderView::AppendTimestamp(time_t time) { - if (AppPreferences::Item()->IgnoreEmoticons) - Append(txt, fore, bg, fore); - else - Emoticor::Get()->AddText(this, txt, fore, fore, bg, fore); + if (time == 0) { + Append("[xx:xx] ", ui_color(B_LINK_HOVER_COLOR)); + return; + } + char timestamp[9] = { '\0' }; + strftime(timestamp, 8, "[%H:%M] ", localtime(&time)); + Append(timestamp, ui_color(B_LINK_HOVER_COLOR)); } - - -void -RenderView::PrepareTheme(Theme *fTheme) -{ - Theme::TimestampFore = COL_TIMESTAMP_DUMMY; - Theme::TimestampBack = COL_TIMESTAMP_DUMMY; - Theme::TimespaceFore = COL_MAX_COLORS; - Theme::TimespaceBack = COL_MAX_COLORS; - Theme::TimespaceFont = MAX_RENDERS; - Theme::TimestampFont = R_TIMESTAMP_DUMMY; - Theme::NormalFore = COL_TEXT; - Theme::NormalBack = COL_TEXT; - Theme::NormalFont = R_TEXT; - Theme::SelectionBack = COL_SELECTION; - - fTheme->WriteLock(); - rgb_color bg = ui_color(B_PANEL_BACKGROUND_COLOR); - rgb_color fg = ui_color(B_PANEL_TEXT_COLOR); - - fTheme->SetForeground(COL_URL, ui_color(B_LINK_TEXT_COLOR)); - fTheme->SetBackground(COL_URL, bg); - - fTheme->SetForeground(COL_TIMESTAMP, fg); - fTheme->SetBackground(COL_TIMESTAMP, bg); - - fTheme->SetForeground(COL_TEXT, fg); - fTheme->SetBackground(COL_TEXT, bg); - - fTheme->SetForeground(COL_ACTION, fg); - fTheme->SetBackground(COL_ACTION, bg); - - fTheme->SetForeground(COL_SELECTION, ui_color(B_MENU_SELECTED_ITEM_TEXT_COLOR)); - fTheme->SetBackground(COL_SELECTION, ui_color(B_MENU_SELECTED_BACKGROUND_COLOR)); - - fTheme->SetForeground(COL_OWNNICK, 0, 0, 255); - fTheme->SetBackground(COL_OWNNICK, bg); - - fTheme->SetForeground(COL_OTHERNICK, 255, 0, 0); - fTheme->SetBackground(COL_OTHERNICK, bg); - - if (Emoticor::Get()->Config() != NULL) - fTheme->SetTextRender(R_EMOTICON, &str); - - fTheme->SetSoftLineIndent(5.0); - fTheme->SetTextMargin(5.0); - - fTheme->WriteUnlock(); -} - - diff --git a/application/views/RenderView.h b/application/views/RenderView.h index 5a56ca6..b880e2b 100644 --- a/application/views/RenderView.h +++ b/application/views/RenderView.h @@ -1,54 +1,21 @@ -#ifndef _RenderView_H -#define _RenderView_H_ +/* + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. + */ +#ifndef _RENDER_VIEW_H +#define _RENDER_VIEW_H #include -#include -class RunView; -class Theme; +class RenderView : public RunView { +public: + RenderView(const char* name); - -enum RenderViewColors { - COL_URL = 0, - COL_TIMESTAMP, - COL_TEXT, - COL_OWNNICK, - COL_OTHERNICK, - COL_ACTION, - COL_SELECTION, - COL_TIMESTAMP_DUMMY, - COL_MAX_COLORS -}; - -enum { - R_URL = 0, - R_TEXT, - R_TIMESTAMP, - R_ACTION, - R_EMOTICON, - R_TIMESTAMP_DUMMY, - MAX_RENDERS -}; - - -class RenderView : public RunView -{ - public: - RenderView(const char* name, const char* smileyConfig = NULL); - void AppendMessage(const char* nick, const char* message, rgb_color nameColor, time_t time = 0); void AppendGenericMessage(const char* message); - void AddEmoticText(const char * txt, rgb_color fore, rgb_color bg); - - protected: - void PrepareTheme(Theme* theme); - - private: - Theme* fTheme; - SmileTextRender str; - + void AppendTimestamp(time_t time = 0); }; -#endif +#endif // _RENDER_VIEW_H diff --git a/libs/librunview/Emoconfig.cpp b/libs/librunview/Emoconfig.cpp index 78e36b6..18a0567 100644 --- a/libs/librunview/Emoconfig.cpp +++ b/libs/librunview/Emoconfig.cpp @@ -7,7 +7,6 @@ #include #include #include -#include "SmileTextRender.h" //tmp BMessage* faces = NULL; diff --git a/libs/librunview/Makefile b/libs/librunview/Makefile index 0e2333e..c3466b0 100644 --- a/libs/librunview/Makefile +++ b/libs/librunview/Makefile @@ -32,10 +32,7 @@ APP_MIME_SIG = # same name (source.c or source.cpp) are included from different directories. # Also note that spaces in folder names do not work well with this Makefile. SRCS = \ - libs/librunview/Theme.cpp \ libs/librunview/RunView.cpp \ - libs/librunview/Utilities.cpp \ - libs/librunview/URLCrunch.cpp \ libs/librunview/Emoticor.cpp \ libs/librunview/Emoconfig.cpp diff --git a/libs/librunview/NormalTextRender.h b/libs/librunview/NormalTextRender.h deleted file mode 100644 index d9a3bda..0000000 --- a/libs/librunview/NormalTextRender.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef _NormalTextRender_H_ -#define _NormalTextRender_H_ - -#include "TextRender.h" -#include -#include - -#include - -class NormalTextRender : public TextRender -{ -public: - - NormalTextRender(BFont f): TextRender() { - font = f; - } - virtual ~NormalTextRender() {}; - - virtual void Render(BView* target, const char* txt, int num, BPoint pos) { - - target->SetFont(&font); - target->DrawString(txt, num, pos); - - - }; - - - virtual float Size() { - return font.Size(); - } - - virtual void GetHeight(font_height* height) { - font.GetHeight(height); - }; - - - virtual void - GetEscapements(const char charArray[], int32 numChars, float escapementArray[]) { - font.GetEscapements(charArray, numChars, escapementArray); - } - -private: - BFont font; - -}; -#endif diff --git a/libs/librunview/RunView.cpp b/libs/librunview/RunView.cpp index 24ac30f..4ca7221 100644 --- a/libs/librunview/RunView.cpp +++ b/libs/librunview/RunView.cpp @@ -1,2368 +1,44 @@ /* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (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 Vision. - * - * The Initial Developer of the Original Code is The Vision Team. - * Portions created by The Vision Team are - * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights - * Reserved. - * - * Contributor(s): Rene Gollent - * Todd Lair - * Alan Ellis - * Andrea Anzani, andrea.anzani@gmail.com + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. */ -#define FORE_WHICH 0 -#define BACK_WHICH 1 -#define FONT_WHICH 2 - -#define OFFVIEW_TIMER (10000LL) -#define ABS(x) (x * ((x<0) ? -1 : 1)) -#define SOFTBREAK_STEP 5 - #include "RunView.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "Theme.h" -#include "URLCrunch.h" -#include "Utilities.h" - - -#define _T(str) (str) - -// cursor data for hovering over URLs - -static unsigned char URLCursorData[] = {16, 1, 2, 2, - 0, 0, 0, 0, 56, 0, 36, 0, 36, 0, 19, 224, 18, 92, 9, 42, - 8, 1, 60, 33, 76, 49, 66, 121, 48, 125, 12, 253, 2, 0, 1, 0, - 0, 0, 0, 0, 56, 0, 60, 0, 60, 0, 31, 224, 31, 252, 15, 254, - 15, 255, 63, 255, 127, 255, 127, 255, 63, 255, 15, 255, 3, 254, 1, 248 - }; - - -struct SoftBreak { - int fOffset; - float fHeight; - float fAscent; -}; - - -struct URL { - int fOffset; - int fLength; - BString fUrl; - - URL(const char* address, int off, int len) - : fOffset (off), fLength (len), fUrl (address) - { } -}; - - -typedef BObjectList urllist; - - -struct SoftBreakEnd { - float fOffset; - - SoftBreakEnd(float offset) - : fOffset(offset) - { } -}; - - -struct FontColor { - int fOffset; - int fWhich; - int fIndex; - rgb_color fColor; -}; - - -struct Line { - char* fText; - time_t fStamp; - urllist* fUrls; - float* fSpaces; - float* fEdges; - FontColor* fFcs; - SoftBreak* fSofties; - float fTop; - float fBottom; - - int fLength; - int fSpace_count; - int fEdge_count; - int fFc_count; - int fSoftie_size; - int fSoftie_used; - - Line(const char* buffer, int fLength, float top, float width, Theme* fTheme, - const char* fStamp_format, time_t fStamp, rgb_color fore, rgb_color back, - rgb_color font); - - ~Line (); - - void Append(const char* buffer, int len, float width, - Theme* fTheme, rgb_color fore, rgb_color back, - rgb_color font); - - void FigureSpaces(); - - void FigureFontColors(int pos, rgb_color fore, rgb_color back, - rgb_color font); - void FigureEdges(Theme* fTheme, float width); - void SoftBreaks(Theme* fTheme, float width); - void AddSoftBreak(SoftBreakEnd, float&, int&, int16&, float&, - float&, Theme*); - int CountChars(int pos, int len); - size_t SetStamp(const char*, bool); - void SelectWord(int*, int*); -}; - - -inline int32 -UTF8_CHAR_LEN (uchar c) -{ - return (((0xE5000000 >> (((c) >> 3) & 0x1E)) & 3) + 1); -} - - -RunView::RunView(BRect frame, const char* name, Theme* theme, - uint32 resizingMode, uint32 flags) +RunView::RunView(const char* name) : - BView(frame, name, resizingMode, flags | B_WILL_DRAW | B_FRAME_EVENTS), - fScroller (NULL), - fTheme (theme), - fWorking (NULL), - fLine_count (0), - fStamp_format (NULL), - fClipping_name (NULL), - fSp_start (0, 0), - fSp_end (0, 0), - fTracking (0), - fTrack_offset (0, 0), - fOff_view_runner (NULL), - fOff_view_time (0), - fResizedirty (false), - fFontsdirty (false), - fMyPopUp (NULL), - fLastClick (0, 0), - fLastClickTime (0) + BTextView(name), + fLastStyled(false) { - memset (fLines, 0, sizeof (fLines)); - fURLCursor = new BCursor (URLCursorData); + MakeEditable(false); + SetStylable(true); + AdoptSystemColors(); - fTheme->ReadLock(); - BView::SetViewColor (B_TRANSPARENT_COLOR); - BView::SetLowColor (fTheme->BackgroundAt (Theme::NormalBack)); - BView::SetHighColor (fTheme->ForegroundAt (Theme::NormalFore)); - fTheme->ReadUnlock(); -} - - -RunView::~RunView() -{ - for (int16 i = 0; i < fLine_count; ++i) - delete fLines[i]; - - delete fWorking; - delete fURLCursor; - delete [] fStamp_format; - delete [] fClipping_name; + text_run run = { 0, BFont(), ui_color(B_PANEL_TEXT_COLOR) }; + fDefaultRun = { 1, {run} }; } void -RunView::AttachedToWindow() +RunView::Append(const char* text, rgb_color color, uint16 fontFace) { - BView::AttachedToWindow(); - RecalcScrollBar (false); - fTheme->WriteLock(); - fTheme->AddView (this); - fTheme->WriteUnlock(); + BFont font; + font.SetFace(fontFace); + text_run run = { 0, font, color }; + text_run_array array = { 1, {run} }; + + Insert(text, &array); + fLastStyled = true; } void -RunView::DetachedFromWindow() +RunView::Append(const char* text) { - fTheme->WriteLock(); - fTheme->RemoveView (this); - fTheme->WriteUnlock(); + if (fLastStyled == false) + Insert(text); + else + Insert(text, &fDefaultRun); + fLastStyled = false; } - - -void -RunView::FrameResized(float start_width, float height) -{ - BView::FrameResized (start_width, height); - - if (IsHidden()) { - fResizedirty = true; - return; - } - ResizeRecalc(); -} - - -void -RunView::TargetedByScrollView (BScrollView* s) -{ - fScroller = s; - BView::TargetedByScrollView (fScroller); -} - - -void -RunView::Show() -{ - if (fFontsdirty) { - FontChangeRecalc(); - // this effectively does the same thing as resize so if both have changed, only - // do the fonts recalculation - fFontsdirty = false; - fResizedirty = false; - } else if (fResizedirty) { - ResizeRecalc(); - fResizedirty = false; - } - BView::Show(); -} - - -void -RunView::Draw(BRect frame) -{ - TextRender* tr = NULL; - - Window()->DisableUpdates(); - Window()->BeginViewTransaction(); - - rgb_color low_color, hi_color, view_color, sel_color, sel_fText; - float height(frame.bottom); - BRect bounds(Bounds()); - BRegion clipper; - bool drawSelection(false); - bool checkSelection(fSp_start != fSp_end); - - clipper.Set (frame); - ConstrainClippingRegion (&clipper); - - fTheme->ReadLock(); - view_color = fTheme->BackgroundAt(Theme::NormalBack); - sel_color = fTheme->BackgroundAt(Theme::SelectionBack); - - if (((sel_color.red + sel_color.blue + sel_color.green) / 3) >= 127) { - sel_fText.red = sel_fText.green = sel_fText.blue = 0; - sel_fText.alpha = 255; - } - else { - sel_fText.red = sel_fText.green = sel_fText.blue = sel_fText.alpha = 255; - } - - BRect remains; - if (fLine_count == 0) - remains = frame; - else if (frame.bottom >= fLines[fLine_count - 1]->fBottom + 1.0) - remains.Set(frame.left, fLines[fLine_count - 1]->fBottom + 1, - frame.right, frame.bottom); - - if (remains.IsValid()) { - SetLowColor (view_color); - FillRect (remains, B_SOLID_LOW); - } - - for (int i = fLine_count - 1; i >= 0; --i) { - Line* line(fLines[i]); - if (line->fBottom < frame.top) - break; - - BRect r (bounds.left, line->fTop, bounds.right, line->fBottom); - - if (!frame.Intersects (r)) - continue; - - float indent (fTheme->TextMargin()); - int place = 0; - - int fore = 0; - int back = 0; - int font = 0; - - height = line->fTop; - - for (int sit = 0; sit < line->fSoftie_used; /*++sit*/sit++) { - int last_len (UTF8_CHAR_LEN (line->fText[line->fSofties[sit].fOffset])); - float left (indent); - float start (0.0); - - // Fill indentation - SetLowColor (view_color); - - SetDrawingMode (B_OP_COPY); - r.Set (0.0, height, indent - 1, height + line->fSofties[sit].fHeight - 1); - FillRect (r, B_SOLID_LOW); - - if (sit) { - int j (place); - - while (--j >= 0) - if ((start = line->fEdges[j]) != 0) - break; - } - - while (place < line->fSofties[sit].fOffset + last_len) { - // Get current foreground color and set - while (fore < line->fFc_count) { - if (line->fFcs[fore].fWhich == FORE_WHICH) { - if (line->fFcs[fore].fOffset > place) - break; - - hi_color = line->fFcs[fore].fColor; - } - - ++fore; - } - - // Get current background color and set - while (back < line->fFc_count) { - if (line->fFcs[back].fWhich == BACK_WHICH) { - if (line->fFcs[back].fOffset > place) - break; - - low_color = line->fFcs[back].fColor; - } - - ++back; - } - - // Get current font and set - while (font < line->fFc_count) { - if (line->fFcs[font].fWhich == FONT_WHICH) { - if (line->fFcs[font].fOffset > place) - break; - - //const BFont &f (fTheme->FontAt (line->fFcs[font].fIndex)); - tr = fTheme->TextRenderAt (line->fFcs[font].fIndex); - //SetFont (&f); - } - - ++font; - } - - int fLength (line->fSofties[sit].fOffset - place + last_len); - - if (fore < line->fFc_count - && line->fFcs[fore].fOffset - place < fLength) - fLength = line->fFcs[fore].fOffset - place; - - if (back < line->fFc_count - && line->fFcs[back].fOffset - place < fLength) - fLength = line->fFcs[back].fOffset - place; - - if (font < line->fFc_count - && line->fFcs[font].fOffset - place < fLength) - fLength = line->fFcs[font].fOffset - place; - - if (checkSelection) { - // case 1: current line marks beginning of selection - if (i == fSp_start.fLine) { - // if we're just prior to the selection, clip fLength to only - // draw up to the selection start - if (place + fLength >= fSp_start.fOffset && place < fSp_start.fOffset) { - fLength = fSp_start.fOffset - place; - drawSelection = false; - } - // we're at the selection, switch drawing color mode - else if (place >= fSp_start.fOffset) { - if (fSp_end.fLine == fSp_start.fLine) { - if (place < fSp_end.fOffset) { - drawSelection = true; - if ((fSp_end.fOffset - place) < fLength) - fLength = fSp_end.fOffset - place; - } else - drawSelection = false; - } else - drawSelection = true; - } else - drawSelection = false; - - } - // case 2: line in between beginning and end of selection, - // highlight entire line - else if (i > fSp_start.fLine && i < fSp_end.fLine) - drawSelection = true; - // case 3: last line of selection, with multiple fLines in between - else if (i == fSp_end.fLine && i != fSp_start.fLine) { - if (place < (fSp_end.fOffset)) { - if (fSp_end.fOffset - place < fLength) - fLength = (fSp_end.fOffset - place); - drawSelection = true; - } else - drawSelection = false; - } else - drawSelection = false; - } - - if (place + fLength == line->fLength) - --fLength; - - int k (place + fLength - 1); - while (line->fEdges[k] == 0) - --k; - - r.Set(left, height, line->fEdges[k] + indent - start, - height + line->fSofties[sit].fHeight - 1); - - SetDrawingMode (B_OP_COPY); - if (drawSelection) - SetLowColor (sel_color); - else - SetLowColor (low_color); - SetHighColor (hi_color); - FillRect (r, B_SOLID_LOW); - - if (drawSelection) - SetHighColor (sel_fText); - - SetDrawingMode (B_OP_OVER); - - if ( sit >= line->fSoftie_used ) - printf("bah. sit is %d and fSoftie_used is %d\n", sit, line->fSoftie_used); - else - tr->Render(this, line->fText + place, - min_c(fLength, line->fLength - place - 1), - BPoint(left, height + line->fSofties[sit].fAscent)); - - left = line->fEdges[k] + indent - start; - - if ((place += fLength) + 1 >= line->fLength) - ++place; - } - - - // Margin after fText - SetDrawingMode(B_OP_COPY); - SetLowColor(view_color); - FillRect(BRect(left + 1, height, bounds.right, - height + line->fSofties[sit].fHeight - 1), - B_SOLID_LOW); - - height += line->fSofties[sit].fHeight; - - if (sit == 0) - indent += fTheme->SoftLineIndent();//fSoftLineIndent; - } - } - - fTheme->ReadUnlock(); - Window()->EndViewTransaction(); - Window()->EnableUpdates(); - ConstrainClippingRegion (NULL); -} - - -void -RunView::SetViewColor(rgb_color color) -{ - assert(memcmp(&color, &B_TRANSPARENT_COLOR, sizeof (rgb_color)) != 0); - BView::SetViewColor(color); -} - - -void -RunView::BuildPopUp() -{ - // This function checks certain criteria (fText is selected, - // TextView is editable, etc) to determine fWhich MenuItems - // to enable and disable - - bool enablecopy (true), - enableselectall (true), - enablelookup (false); - BString querystring(""); - - if (fSp_start == fSp_end) - enablecopy = false; // no selection - - if (!fLine_count) - enableselectall = false; - - if (enablecopy) { - enablelookup = true; // has a selection less than 32 chars long - GetSelectionText(querystring); - } - - fMyPopUp = new BPopUpMenu("IRCView Context Menu", false, false); - - BMenuItem* item; - - BMessage* lookup; - lookup = new BMessage(M_LOOKUP_WEBSTER); - lookup->AddString("string", querystring); - item = new BMenuItem(_T("Lookup (Dictionary)"), lookup); - item->SetEnabled(enablelookup); - item->SetTarget(this); - fMyPopUp->AddItem(item); - - lookup = new BMessage(M_LOOKUP_GOOGLE); - lookup->AddString("string", querystring); - item = new BMenuItem(_T("Lookup (Google)"), lookup); - item->SetEnabled(enablelookup); - item->SetTarget(this); - fMyPopUp->AddItem (item); - - lookup = new BMessage(M_LOOKUP_ACRONYM); - lookup->AddString("string", querystring); - item = new BMenuItem(_T("Lookup (Acronym Finder)"), lookup); - item->SetEnabled(enablelookup); - item->SetTarget(this); - fMyPopUp->AddItem(item); - - fMyPopUp->AddSeparatorItem(); - - item = new BMenuItem(_T("Copy"), new BMessage(B_COPY), 'C'); - item->SetEnabled(enablecopy); - item->SetTarget(this); - fMyPopUp->AddItem(item); - - item = new BMenuItem(_T("Select All"), new BMessage(B_SELECT_ALL), 'A'); - item->SetEnabled(enableselectall); - item->SetTarget(this); - fMyPopUp->AddItem (item); - - fMyPopUp->AddSeparatorItem(); - - item = new BMenuItem(_T("Clear"), new BMessage(M_CLEAR)); - item->SetTarget(this); - fMyPopUp->AddItem(item); - - fMyPopUp->SetFont(be_plain_font); -} - - -bool -RunView::CheckClickBounds(const SelectPos& s, const BPoint& point) const -{ - return ((point.x <= fLines[s.fLine]->fEdges[fLines[s.fLine]->fLength - 1]) - && (point.y <= fLines[s.fLine]->fBottom)); -} - - -void -RunView::MouseDown(BPoint point) -{ - if (!fLine_count) - return; - - BMessage* msg(Window()->CurrentMessage()); - uint32 buttons; - uint32 mouseModifiers; - bigtime_t sysTime; - msg->FindInt64("when", &sysTime); - uint16 clicks = CheckClickCount(point, fLastClick, sysTime, fLastClickTime, fClickCount) % 3; - msg->FindInt32("buttons", reinterpret_cast(&buttons)); - msg->FindInt32("modifiers", reinterpret_cast(&mouseModifiers)); - - SelectPos s(PositionAt (point)); - bool inBounds(CheckClickBounds (s, point)); - - if (buttons == B_SECONDARY_MOUSE_BUTTON - && (mouseModifiers & B_SHIFT_KEY) == 0 - && (mouseModifiers & B_COMMAND_KEY) == 0 - && (mouseModifiers & B_CONTROL_KEY) == 0 - && (mouseModifiers & B_OPTION_KEY) == 0 - && (mouseModifiers & B_MENU_KEY) == 0) { - SelectPos start(s), - end(s); - - // select word - if (inBounds && !IntersectSelection (s, s)) { - fLines[s.fLine]->SelectWord(&start.fOffset, &end.fOffset); - - Select (start, end); - } - - BuildPopUp(); - fMyPopUp->Go ( - ConvertToScreen (point), - true, - false); - - delete fMyPopUp; - fMyPopUp = 0; - return; - } - - if (buttons == B_PRIMARY_MOUSE_BUTTON - && (mouseModifiers & B_SHIFT_KEY) == 0 - && (mouseModifiers & B_COMMAND_KEY) == 0 - && (mouseModifiers & B_CONTROL_KEY) == 0 - && (mouseModifiers & B_OPTION_KEY) == 0 - && (mouseModifiers & B_MENU_KEY) == 0) { - SelectPos start (s), - end (s); - - switch (clicks) { - case 2: { - if (inBounds) { - // select word - fLines[s.fLine]->SelectWord(&start.fOffset, &end.fOffset); - Select(start, end); - return; - } - } - break; - - case 0: { - if (inBounds) { - start.fOffset = 0; - end.fOffset = fLines[s.fLine]->fLength - 1; - Select(start, end); - return; - } - } - break; - - default: { - if (!inBounds || !IntersectSelection (s, s)) - Select (s, s); - SetMouseEventMask(B_POINTER_EVENTS); - fTracking = 1; - fTrack_offset = s; - return; - } - } - } else if (buttons == B_PRIMARY_MOUSE_BUTTON - && (mouseModifiers & B_SHIFT_KEY) != 0 - && (mouseModifiers & B_COMMAND_KEY) == 0 - && (mouseModifiers & B_CONTROL_KEY) == 0 - && (mouseModifiers & B_OPTION_KEY) == 0 - && (mouseModifiers & B_MENU_KEY) == 0) { - if (s.fLine < fSp_start.fLine || s.fOffset < fSp_start.fOffset) { - Select(s, fSp_end); - fTrack_offset = SelectPos(fSp_end.fLine, (fSp_end.fOffset > 0) ? fSp_end.fOffset - 1 : fSp_end.fOffset); - } else { - Select(fSp_start, s); - fTrack_offset = fSp_start; - } - - SetMouseEventMask(B_POINTER_EVENTS); - fTracking = 2; - } -} - - -void -RunView::CheckURLCursor(BPoint point) -{ - if (!fLine_count) - return; - - SelectPos s = PositionAt (point); - - if (!fLines[s.fLine]->fUrls) { - // if there aren't any URLs in the current line, go back to default - SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); - return; - } - Line* curline (fLines[s.fLine]); - - for (int32 i = 0; i < curline->fUrls->CountItems(); i++) { - URL* current = curline->fUrls->ItemAt(i); - if ((s.fOffset >= current->fOffset) - && (s.fOffset <= current->fOffset + current->fLength)) { - SetViewCursor (fURLCursor); - return; - } - } - - // no URLs found, set back to default - SetViewCursor (B_CURSOR_SYSTEM_DEFAULT); -} - - -void -RunView::MouseMoved(BPoint point, uint32 transit, const BMessage* msg) -{ - if (fTracking == 0 - && fLine_count - && (transit == B_ENTERED_VIEW - || transit == B_INSIDE_VIEW)) - CheckURLCursor (point); - - - if (!fLine_count || fTracking == 0) { - BView::MouseMoved (point, transit, msg); - return; - } - - switch (transit) { - case B_ENTERED_VIEW: - if (fOff_view_runner) { - delete fOff_view_runner; - fOff_view_runner = 0; - } - - if (fTracking == 1 || fTracking == 2) - ExtendTrackingSelect (point); - - break; - - case B_EXITED_VIEW: - if (fTracking == 1 || fTracking == 2) - ShiftTrackingSelect (point, true, OFFVIEW_TIMER); - break; - - case B_OUTSIDE_VIEW: - - if (fTracking == 1 || fTracking == 2) { - bigtime_t now (system_time()); - - ShiftTrackingSelect ( - point, - false, - max_c (0LL, min_c (OFFVIEW_TIMER, OFFVIEW_TIMER - (now - fOff_view_time)))); - } - break; - - case B_INSIDE_VIEW: - - if ((fTracking == 1) && (fSp_start != fSp_end)) { - BMessage msg (B_MIME_DATA); - BString fText; - - GetSelectionText (fText); - msg.AddData ( - "text/plain", - B_MIME_TYPE, - fText.String(), - fText.Length() + 1); - - BString clip_name (" Clipping"); - - if (fClipping_name) - clip_name.Prepend (fClipping_name); - else - clip_name.Prepend ("RunView"); - - msg.AddString ("be:clip_name", clip_name.String()); - msg.AddInt32 ("be:actions", B_COPY_TARGET); - - BRect frame ( - fLines[fSp_start.fLine]->fEdges[fSp_start.fOffset], - fLines[fSp_start.fLine]->fTop, - fLines[fSp_end.fLine]->fEdges[fSp_end.fOffset], - fLines[fSp_end.fLine]->fBottom); - - if (fSp_start.fLine != fSp_end.fLine) { - frame.left = 0.0; - frame.right = Bounds().right; - } - // selection lies within the bounds of a line, check - // if it fLines on one of the wrapped subfLines and calculate rectangle - // appropriately - else { - Line* line (fLines[fSp_start.fLine]); - float left (line->fEdges[fSp_start.fOffset]), - top (line->fTop), - right (line->fEdges[fSp_end.fOffset]), - bottom (line->fBottom); - int top_softie (0), bottom_softie (0); - bool start_found (false); - bool end_found (false); - - if (line->fSoftie_used) { - if (fSp_start.fOffset < line->fSofties[0].fOffset) - start_found = true; - - if (fSp_end.fOffset < line->fSofties[0].fOffset) - end_found = true; - } - - if (!end_found) - for (int16 sit = 1; sit < line->fSoftie_used; ++sit) { - if (!start_found && fSp_start.fOffset < line->fSofties[sit].fOffset) { - left = (float)(line->fEdges[fSp_start.fOffset] - - line->fEdges[line->fSofties[sit-1].fOffset]); - - top += (sit) * line->fSofties[sit].fHeight; - top_softie = sit; - start_found = true; - } - - if (fSp_end.fOffset < line->fSofties[sit].fOffset) { - right = (float) line->fEdges[fSp_end.fOffset] - - (float) line->fEdges[line->fSofties[sit-1].fOffset]; - - bottom = top + (sit - (float) top_softie + 1) * line->fSofties[sit].fHeight; - bottom_softie = sit; - end_found = true; - break; - } - } - if (!end_found) { - int32 soft_count = (line->fSoftie_used >= 2) ? - line->fSoftie_used - 2 : 0; - right = (float) line->fEdges[line->fLength - 1] - - (float) line->fEdges[line->fSofties[soft_count].fOffset]; - bottom_softie = soft_count - 2; - - } - if (right < left || (bottom_softie - top_softie) > 0) { - left = 0.0; - right = Bounds().right; - } - - frame.Set (left, top, right, bottom); - frame.OffsetBy (fTheme->TextMargin(), 0.0); - } - - if (frame.Height() > Bounds().Height()) - frame = Bounds(); - - DragMessage (&msg, frame); - - fTracking = 3; - } else if (fTracking == 1 || fTracking == 2) - ExtendTrackingSelect (point); - break; - } -} - - -void -RunView::MouseUp(BPoint point) -{ - SelectPos s (PositionAt (point)); - bool url_handle (false); - - if (!fLine_count) { - fTracking = 0; - return; - } - - if (fTracking == 1) { - Line* curline (fLines[s.fLine]); - if (curline->fUrls) { - for (int32 i = 0; i < curline->fUrls->CountItems(); i++) { - URL* current = curline->fUrls->ItemAt(i); - if ((s.fOffset >= current->fOffset) - && (s.fOffset <= current->fOffset + current->fLength)) { - - LoadURL (current->fUrl.String()); - url_handle = true; - break; - } - } - } - if (!url_handle && s == fTrack_offset) - Select (s, s); - } - - if (fOff_view_runner) { - delete fOff_view_runner; - fOff_view_runner = 0; - } - - fTracking = 0; -} - - -void -RunView::ExtendTrackingSelect(BPoint point) -{ - SelectPos s (PositionAt (point)); - - if (s.fLine < fTrack_offset.fLine || (s.fLine == fTrack_offset.fLine && s.fOffset < fTrack_offset.fOffset)) { - Select (s, fTrack_offset); - fTracking = 2; - } else if (s.fLine > fTrack_offset.fLine || (s.fLine == fTrack_offset.fLine && s.fOffset > fTrack_offset.fOffset)) { - Select (fTrack_offset, s); - fTracking = 2; - } -} - - -void -RunView::ShiftTrackingSelect(BPoint point, bool move, bigtime_t timer) -{ - BRect bounds (Bounds()); - - if (fOff_view_runner) { - delete fOff_view_runner; - fOff_view_runner = 0; - } - - if (point.y < bounds.top) { - if (bounds.top > 0.0) { - float delta (bounds.top - point.y); - - if (fOff_view_runner == 0) { - BMessage* msg (new BMessage (M_OFFVIEW_SELECTION)); - - msg->AddFloat ("delta", delta); - msg->AddBool ("bottom", false); - msg->AddPoint ("point", point); - - fOff_view_runner = new BMessageRunner ( - BMessenger (this), - msg, - timer == 0LL ? OFFVIEW_TIMER : timer); - - } - - if (move || timer == 0) { - delta = (float) max_c (ABS (ceil (delta / 2.0)), 10.0); - delta = (float) min_c (delta, Bounds().Height()); - - if (bounds.top - delta < 0.0) - delta = bounds.top; - - ScrollBy (0.0, -delta); - fOff_view_time = system_time(); - } - } - - point.x = 0.0; - point.y = Bounds().top; - ExtendTrackingSelect (point); - } - - if (point.y > bounds.bottom) { - Line* line (fLines[fLine_count-1]); - if (line - && line->fBottom > bounds.bottom) { - float delta (point.y - bounds.bottom); - - if (fOff_view_runner == 0) { - BMessage* msg (new BMessage (M_OFFVIEW_SELECTION)); - - msg->AddFloat ("delta", delta); - msg->AddBool ("bottom", true); - msg->AddPoint ("point", point); - - fOff_view_runner = new BMessageRunner ( - BMessenger (this), - msg, - timer == 0LL ? OFFVIEW_TIMER : timer); - - } - - if (move || timer == 0) { - delta = (float) max_c (ABS (ceil (delta / 2.0)), 10.0); - delta = (float) min_c (delta, Bounds().Height()); - - if (bounds.bottom + delta > line->fBottom) - delta = line->fBottom - bounds.bottom; - - ScrollBy (0.0, delta); - fOff_view_time = system_time(); - } - } - - point.x = Bounds().right; - point.y = Bounds().bottom; - ExtendTrackingSelect (point); - } else - ExtendTrackingSelect (point); -} - - -void -RunView::MessageReceived(BMessage* msg) -{ - switch (msg->what) - { - case M_THEME_FOREGROUND_CHANGE: - case M_THEME_BACKGROUND_CHANGE: - { - if (!IsHidden()) - Invalidate (Bounds()); - break; - } - case M_THEME_FONT_CHANGE: - { - Theme* save (fTheme); - - fTheme = NULL; - SetTheme (save); - break; - } - case B_SELECT_ALL: - SelectAll(); - break; - - case B_COPY: - { - if (fSp_start != fSp_end - && be_clipboard->Lock()) { - BString fText; - GetSelectionText (fText); - - be_clipboard->Clear(); - - BMessage* msg (be_clipboard->Data()); - msg->AddData ("text/plain", B_MIME_TYPE, fText.String(), fText.Length()); - - be_clipboard->Commit(); - be_clipboard->Unlock(); - } - break; - } - case M_OFFVIEW_SELECTION: - { - BPoint point; - float delta; - bool bottom; - - msg->FindPoint ("point", &point); - msg->FindBool ("bottom", &bottom); - msg->FindFloat ("delta", &delta); - - if (bottom) - point.y = Bounds().bottom + delta; - else - point.y = Bounds().top - delta; - - ShiftTrackingSelect (point, true, OFFVIEW_TIMER); - break; - } - case M_LOOKUP_WEBSTER: - { - BString lookup; - msg->FindString ("string", &lookup); - lookup = StringToURI (lookup.String()); - lookup.Prepend ("http://www.m-w.com/cgi-bin/dictionary?va="); - LoadURL (lookup.String()); - break; - } - case M_LOOKUP_GOOGLE: - { - BString lookup; - msg->FindString ("string", &lookup); - lookup = StringToURI (lookup.String()); - lookup.Prepend ("http://www.google.com/search?q="); - LoadURL (lookup.String()); - break; - } - case M_LOOKUP_ACRONYM: - { - BString lookup; - msg->FindString ("string", &lookup); - lookup = StringToURI (lookup.String()); - lookup.Prepend ("http://www.acronymfinder.com/af-query.asp?String=exact&Acronym="); - lookup.Append ("&Find=Find"); - LoadURL (lookup.String()); - break; - } - case M_CLEAR: - Clear(); - break; - - default: - BView::MessageReceived (msg); - } -} - - -void -RunView::ResizeRecalc() -{ - float width (Bounds().Width() - (fTheme->TextMargin() * 2)); - int fSoftie_size (0), fSoftie_used (0); - SoftBreak* fSofties (NULL); - BRect bounds (Bounds()); - BRegion region; - float top (0.0); - - fTheme->ReadLock(); - for (int16 i = 0; i < fLine_count; ++i) { - float old_top (fLines[i]->fTop), old_bottom (fLines[i]->fBottom); - if (fSoftie_size < fLines[i]->fSoftie_used) { - delete [] fSofties; - fSofties = new SoftBreak [fSoftie_size = fLines[i]->fSoftie_size]; - } - - fSoftie_used = fLines[i]->fSoftie_used; - memcpy (fSofties, fLines[i]->fSofties, (fSoftie_used * sizeof (SoftBreak))); - - fLines[i]->fTop = top; - fLines[i]->SoftBreaks (fTheme, width); - top = fLines[i]->fBottom + (float) 1.0; - - BRect r (0.0, fLines[i]->fTop, bounds.right, fLines[i]->fBottom); - - if (bounds.Intersects (r) - && (old_top != fLines[i]->fTop - || old_bottom != fLines[i]->fBottom - || fSoftie_used != fLines[i]->fSoftie_used - || memcmp (fSofties, fLines[i]->fSofties, fSoftie_used * sizeof (SoftBreak)))) - region.Include (r); - } - - fTheme->ReadUnlock(); - - if (Window()) { - if (RecalcScrollBar (true)) - Invalidate (Bounds()); - else { - int32 count (region.CountRects()), j; - - for (j = 0; j < count; ++j) - Invalidate (region.RectAt (j)); - - if (top <= bounds.bottom) { - BRect r (bounds); - - r.top = top; - Invalidate (r); - } - } - - Window()->Sync(); - } - - if (fWorking) fWorking->fTop = top; - delete [] fSofties; -} - - -void -RunView::FontChangeRecalc() -{ - float width (Bounds().Width() - (fTheme->TextMargin() * 2)); - float top (0.0); - - for (int16 i = 0; i < fLine_count; ++i) { - fLines[i]->fTop = top; - - fLines[i]->FigureSpaces(); - fLines[i]->FigureEdges (fTheme, width); - - top = fLines[i]->fBottom + (float) 1.0; - } - - if (fWorking) - fWorking->fTop = top; - - RecalcScrollBar (false); - if (!IsHidden()) - Invalidate (Bounds()); - if (Window()) Window()->UpdateIfNeeded(); -} - - -bool -RunView::RecalcScrollBar(bool constrain) -{ - BScrollBar* bar; - - if (fScroller == NULL - || (bar = fScroller->ScrollBar (B_VERTICAL)) == NULL) - return false; - - float value (bar->Value()); - BRect bounds (Bounds()); - bool changed (false); - float bottom (0.0); - float scrollMin, scrollMax; - - bar->GetRange (&scrollMin, &scrollMax); - - if (fLine_count - && (bounds.Contains (BPoint (0.0, 0.0)) == false - || bounds.Contains (BPoint (0.0, fLines[fLine_count - 1]->fBottom)) == false)) { - bottom = fLines[fLine_count - 1]->fBottom + 5; - bar->SetProportion (bounds.Height() / bottom); - bar->SetSteps (10.0, bounds.Height()); - - bottom -= bounds.Height(); - } - - // We don't want the bar to cause a draw/copybits, so we restrict the - // clipping region to nothing - - if (constrain) { - BRegion region; - ConstrainClippingRegion (®ion); - } - - if (scrollMax != bottom) { - bar->SetRange (0.0, bottom); - - if (value == scrollMax || scrollMin == scrollMax) { - bar->SetValue (bottom); - changed = true; - } - } - - if (constrain) - ConstrainClippingRegion (NULL); - - return changed; -} - - -void -RunView::Append(const char* buffer, rgb_color fore, rgb_color back, - rgb_color font, time_t time) -{ - Append(buffer, strlen(buffer), fore, back, font, time); -} - - -void -RunView::Append(const char* buffer, int32 len, rgb_color fore, rgb_color back, - rgb_color font, time_t time) -{ - if (buffer == NULL) - return; - float width(Bounds().Width() - 10); - int32 place(0); - - fTheme->ReadLock(); - - while (place < len) { - int32 end(place); - - while (end < len && buffer[end] != '\n') - ++end; - - if (end < len) - ++end; - - if (fWorking) { - URLCrunch crunch (buffer + place, end - place); - BString temp; - int32 url_offset (0), - last_offset (0); - - while ((url_offset = crunch.Crunch (&temp)) != B_ERROR) { - fWorking->Append(buffer + place, (url_offset - last_offset), - width, fTheme, fore, back, font); - - fWorking->Append(temp.String(), temp.Length(), width, fTheme, - ui_color(B_LINK_TEXT_COLOR), back, fore); - - place += (url_offset - last_offset) + temp.Length(); - last_offset = url_offset + temp.Length(); - } - - if (place < end) - fWorking->Append(buffer + place, end - place, width, fTheme, - fore, back, font); - } - else { - float top(0.0); - - if (fLine_count > 0) - top = fLines[fLine_count - 1]->fBottom + (float) 1.0; - - fWorking = new Line(buffer + place, 0, top, width, fTheme, - fStamp_format, time, fore, back, font); - - URLCrunch crunch(buffer + place, end - place); - BString temp; - int32 url_offset(0), - last_offset(0); - - while ((url_offset = crunch.Crunch(&temp)) != B_ERROR) { - fWorking->Append(buffer + place, (url_offset - last_offset), - width, fTheme, fore, back, font); - fWorking->Append(temp.String(), temp.Length(), width, fTheme, - ui_color(B_LINK_TEXT_COLOR), back, fore); - - place += (url_offset - last_offset) + temp.Length(); - last_offset = url_offset + temp.Length(); - } - - if (place < end) - fWorking->Append(buffer + place, end - place, width, - fTheme, fore, back, font); - } - - if (fWorking->fLength - && fWorking->fText[fWorking->fLength - 1] == '\n') { - bool chopped; - - if (Window()) Window()->DisableUpdates(); - - if ((chopped = (fLine_count == LINE_COUNT))) { - Line* first(fLines[0]); - float shift(first->fBottom + 1); - - for (int16 i = 1; i < LINE_COUNT; ++i) { - fLines[i]->fTop -= shift; - fLines[i]->fBottom -= shift; - - fLines[i - 1] = fLines[i]; - } - - fWorking->fTop -= shift; - fWorking->fBottom -= shift; - - delete first; - - if (fSp_start.fLine > 0) - fSp_start.fLine--; - else - fSp_start.fOffset = 0; - - if (fSp_end.fLine > 0) - fSp_end.fLine--; - else - fSp_end.fOffset = 0; - - // Recalc the scrollbar so that we have clean drawing - // after the line has been removed - --fLine_count; - RecalcScrollBar(true); - } - - fLines[fLine_count++] = fWorking; - RecalcScrollBar(true); - - Invalidate(Bounds()); - - if (Window()) { - Window()->EnableUpdates(); - Window()->UpdateIfNeeded(); - } - - fWorking = NULL; - } - - place = end; - } - - fTheme->ReadUnlock(); -} - - -void -RunView::Clear() -{ - for (int16 i = 0; i < fLine_count; ++i) - delete fLines[i]; - - fLine_count = 0; - RecalcScrollBar(true); - Invalidate(); - - fSp_start.fLine = 0; - fSp_start.fOffset = 0; - fSp_end = fSp_start; - - if (fWorking) - fWorking->fTop = 0.0; -} - - -int16 -RunView::LineCount() const -{ - return fLine_count; -} - - -const char * -RunView::LineAt(int which) const -{ - if (which < 0 || which >= fLine_count) - return NULL; - - return fLines[which]->fText; -} - - -void -RunView::SetTimeStampFormat(const char* format) -{ - if ((format == NULL - && fStamp_format == NULL) - || (format != NULL - && fStamp_format != NULL - && strcmp(format, fStamp_format) == 0)) - return; - - bool was_on(false); - - if (fStamp_format) { - delete [] fStamp_format; - fStamp_format = NULL; - was_on = true; - } - - if (format) - fStamp_format = strcpy(new char [strlen (format) + 1], format); - - float width(Bounds().Width() - (fTheme->TextMargin() * 2)); - float top(0.0); - - fTheme->ReadLock(); - for (int16 i = 0; i < fLine_count; ++i) { - fLines[i]->fTop = top; - - fLines[i]->SetStamp(fStamp_format, was_on); - fLines[i]->FigureSpaces(); - fLines[i]->FigureEdges(fTheme, width); - - top = fLines[i]->fBottom + 1; - } - fTheme->ReadUnlock(); - - if (fWorking) { - fWorking->fTop = top; - fWorking->SetStamp(fStamp_format, was_on); - } - - RecalcScrollBar(false); - Invalidate(Bounds()); - if (Window()) Window()->UpdateIfNeeded(); -} - - -void -RunView::SetTheme(Theme* t) -{ - if (t == NULL || fTheme == t) - return; - - fTheme = t; - - if (IsHidden()) { - fFontsdirty = true; - return; - } - FontChangeRecalc(); -} - - -SelectPos -RunView::PositionAt(BPoint point) const -{ - int i, lfIndex(0); - SelectPos pos(-1, 0); - - if (fLine_count == 0) - return pos; - - // find the line - for (i = 0; i < fLine_count; ++i) { - if (fLines[i]->fTop > point.y) - break; - lfIndex = i; - } - - // check to make sure we actually did find a line and not just run into fLine_count - if (fLines[lfIndex]->fBottom < point.y) { - pos.fLine = fLine_count - 1; - pos.fOffset = fLines[fLine_count - 1]->fLength; - return pos; - } - - float height(fLines[lfIndex]->fTop); - int sfIndex(0); - - for (i = 0; i < fLines[lfIndex]->fSoftie_used; ++i) { - if (height > point.y) - break; - - sfIndex = i; - height += fLines[lfIndex]->fSofties[i].fHeight; - } - - float margin(fTheme->TextMargin()); - float width(0); - int start(0); - - if (sfIndex) { - int offset(fLines[lfIndex]->fSofties[sfIndex - 1].fOffset); - - width = fLines[lfIndex]->fEdges[offset]; - start = offset + UTF8_CHAR_LEN (fLines[lfIndex]->fText[offset]); - } - - for (i = start; i <= fLines[lfIndex]->fSofties[sfIndex].fOffset; ++i) - if (fLines[lfIndex]->fEdges[i] + margin - width >= point.x) - break; - - pos.fLine = lfIndex; - pos.fOffset = min_c(i, fLines[lfIndex]->fSofties[sfIndex].fOffset); - if (pos.fOffset > 0) pos.fOffset += UTF8_CHAR_LEN (fLines[pos.fLine]->fText[pos.fOffset]); - - return pos; -} - - -BPoint -RunView::PointAt(SelectPos s) const -{ - return BPoint(fLines[s.fLine]->fTop + fLines[s.fLine]->fBottom / 2, fLines[s.fLine]->fEdges[s.fOffset]); -} - - -void -RunView::GetSelectionText(BString& string) const -{ - if (fSp_start == fSp_end) - return; - - if (fSp_start.fLine == fSp_end.fLine) { - const char* line(LineAt (fSp_start.fLine)); - string.Append(line + fSp_start.fOffset, fSp_end.fOffset - fSp_start.fOffset); - return; - } - - for (int32 i = fSp_start.fLine; i <= fSp_end.fLine; i++) { - const char* line(LineAt (i)); - if (i == fSp_start.fLine) { - line += fSp_start.fOffset; - string.Append(line); - } else if (i == fSp_end.fLine) { - string.Append(line, fSp_end.fOffset); - break; - } else - string.Append(line); - } -} - - -bool -RunView::IntersectSelection(const SelectPos& start, const SelectPos& end) const -{ - if (fSp_start.fLine == fSp_end.fLine) { - if (start.fLine == fSp_start.fLine && start.fOffset >= fSp_start.fOffset && start.fOffset < fSp_end.fOffset) - return true; - if (end.fLine == fSp_start.fLine && end.fOffset >= fSp_start.fOffset && end.fOffset < fSp_end.fOffset) - return true; - } else { - if (start.fLine > fSp_start.fLine && start.fLine < fSp_end.fLine) - return true; - if (end.fLine > fSp_start.fLine && end.fLine < fSp_end.fLine) - return true; - if (start.fLine == fSp_start.fLine && start.fOffset >= fSp_start.fOffset) - return true; - if (end.fLine == fSp_start.fLine && end.fOffset >= fSp_start.fOffset) - return true; - if (start.fLine == fSp_end.fLine && start.fOffset < fSp_end.fOffset) - return true; - if (end.fLine == fSp_end.fLine && end.fOffset < fSp_end.fOffset) - return true; - } - - return false; -} - - -BRect -RunView::GetTextFrame(const SelectPos& start, const SelectPos& end) const -{ - return BRect(0.0, fLines[(start.fLine > 0) ? (start.fLine - 1) : 0]->fTop, - Bounds().Width(), fLines[end.fLine]->fBottom); -} - - -void -RunView::Select(const SelectPos& start, const SelectPos& end) -{ - if (fSp_start != fSp_end) { - if (start == end || !IntersectSelection (start, end)) { - BRect frame (GetTextFrame (fSp_start, fSp_end)); - - fSp_start = start; - fSp_end = start; - Invalidate (frame); - } else { - if (fSp_start.fLine < start.fLine || (fSp_start.fLine == start.fLine && fSp_start.fOffset < start.fOffset)) { - BRect frame (GetTextFrame (fSp_start, start)); - - fSp_start = start; - Invalidate (frame); - } - - if (end.fLine < fSp_end.fLine || (fSp_end.fLine == end.fLine && end.fOffset < fSp_end.fOffset)) { - BRect frame (GetTextFrame (end, fSp_end)); - - fSp_end = end; - Invalidate (frame); - } - } - } - - if (fSp_start == fSp_end) { - fSp_start = start; - fSp_end = end; - - if (fSp_start != fSp_end) { - BRect frame (GetTextFrame (start, end)); - - Invalidate (frame); - } - } else { // extension - if (start.fLine < fSp_start.fLine || (start.fLine == fSp_start.fLine && start.fOffset < fSp_start.fOffset)) { - BRect frame (GetTextFrame (start, fSp_start)); - - fSp_start = start; - Invalidate (frame); - } - - if (end.fLine > fSp_end.fLine || (end.fLine == fSp_end.fLine && end.fOffset > fSp_end.fOffset)) { - BRect frame (GetTextFrame (fSp_end, end)); - - fSp_end = end; - Invalidate (frame); - } - } -} - - -void -RunView::SelectAll() -{ - if (fLine_count) { - fSp_start = SelectPos (0, 0); - fSp_end = SelectPos (fLine_count - 1, fLines[fLine_count-1]->fLength); - Invalidate(Bounds()); - } -} - - -void -RunView::SetClippingName(const char* name) -{ - delete [] fClipping_name; - fClipping_name = new char[strlen(name) + 1]; - memcpy (fClipping_name, name, strlen(name)); - fClipping_name[strlen(name)] = '\0'; -} - - -bool -RunView::FindText(const char* text) -{ - bool result (false); - if (text != NULL) { - for (int32 i = 0; i < fLine_count; i++) { - char* offset (NULL); - if ((offset = strstr((const char*)fLines[i], text)) != NULL) { - SelectPos start (i, offset - text), - end (i, (offset - text) + strlen(text)); - Select(start, end); - ScrollTo(0.0, fLines[i]->fTop); - result = true; - break; - } - } - } - return result; -} - - -void RunView::LoadURL(const char* url) -{ - BString argument (url); - if (argument.FindFirst ("://") == B_ERROR) { - - if (argument.IFindFirst ("www") == 0) - argument.Prepend ("http://"); - - else if (argument.IFindFirst ("ftp") == 0) - argument.Prepend ("ftp://"); - } - - const char* args[] = { argument.String(), 0 }; - - if (argument.IFindFirst ("file:") == 0) { - // The URL is guaranteed to be at least "file:/" - BString file(argument.String() + 5); - - // todo: Should probably see if the file exists before going through - // all this, but, oh well... ;) - file.Prepend("/boot/beos/system/Tracker "); - file += " &"; // just in case - - system(file.String()); - } else if (argument.IFindFirst ("mailto:") == 0) { - be_roster->Launch ("text/x-email", 1, const_cast(args)); - } else { - be_roster->Launch ("text/html", 1, const_cast(args)); - } -} - - -void RunView::ScrollToBottom() -{ - if (fLine_count != 0) { - BScrollBar* scroll = fScroller->ScrollBar(B_VERTICAL); - if (scroll != NULL) scroll->SetValue(fLines[fLine_count - 1]->fBottom); - ScrollTo(0.0, fLines[fLine_count - 1]->fBottom); - }; -}; - - -void RunView::ScrollToSelection() -{ - if (fLine_count == 0) return; - - if (fSp_start != fSp_end) - ScrollTo(0.0, fLines[fSp_start.fLine]->fTop); - -}; - - -Line::Line(const char* buffer, int len, float top, float width, Theme* theme, - const char* stamp_format, time_t stamp_time, rgb_color fore, - rgb_color back, rgb_color font) - : - fText(NULL), - fStamp(stamp_time), - fUrls(NULL), - fSpaces(NULL), - fEdges(NULL), - fFcs(NULL), - fSofties(NULL), - fTop(top), - fBottom(0.0), - fLength(len), - fSpace_count(0), - fEdge_count(0), - fFc_count(0), - fSoftie_size(0), - fSoftie_used(0) -{ - // Very important to call SetStamp before Append, It would look real funny otherwise! - SetStamp(stamp_format, false ); - Append(buffer, len, width, theme, fore, back, font); -} - - -Line::~Line() -{ - delete [] fSpaces; - delete [] fEdges; - delete [] fFcs; - delete [] fText; - delete [] fSofties; - - if (fUrls) { - while (fUrls->CountItems() > 0) - delete fUrls->RemoveItemAt(0L); - delete fUrls; - } -} - - -void -Line::Append(const char* buffer, int len, float width, Theme* theme, - rgb_color fore, rgb_color back, rgb_color font) -{ - int save (fLength); - char* new_fText; - - new_fText = new char [fLength + len + 1]; - - if (fText != NULL) { - memcpy (new_fText, fText, fLength); - delete [] fText; - } - - memcpy (new_fText + fLength, buffer, len); - fLength += len; - new_fText[fLength] = '\0'; - - // replace Tab chars with spaces. - // todo: This should be temp until RunView can properly - // display tabs. - for ( char* pos = new_fText + save; *pos; ++pos ) { - if ( '\t' == *pos ) { - *pos = ' '; - } - } - - fText = new_fText; - - FigureFontColors(save, fore, back, font); - - if (fore == ui_color(B_LINK_TEXT_COLOR)) { - if (!fUrls) - fUrls = new urllist; - fUrls->AddItem (new URL (buffer, save, len)); - } - - if (fText[fLength - 1] == '\n') { - FigureSpaces(); - FigureEdges (theme, width); - } -} - - -void -Line::FigureSpaces() -{ - const char spacers[] = " \t\n-\\/"; - const char* buffer (fText); - size_t offset (0), n; - int16 count (0); - - delete [] fSpaces; - fSpace_count = 0; - while ((n = strcspn (buffer + offset, spacers)) < fLength - offset) { - ++count; - offset += n + 1; - } - - fSpaces = new float [count]; - - offset = 0; - while ((n = strcspn (buffer + offset, spacers)) < fLength - offset) { - fSpaces[fSpace_count++] = (int16)(n + offset); - offset += n + 1; - } -} - - -void -Line::FigureFontColors(int pos, rgb_color fore, rgb_color back, rgb_color font) -{ - if (fFc_count) { - int last_fore = -1; - int last_back = -1; - int last_font = -1; - int i; - - // we have fFcs, so we backtrack for last of each fWhich - for (i = fFc_count - 1; i >= 0; --i) { - if (last_fore < 0 && fFcs[i].fWhich == FORE_WHICH) - last_fore = i; - else if (last_back < 0 && fFcs[i].fWhich == BACK_WHICH) - last_back = i; - else if (last_font < 0 && fFcs[i].fWhich == FONT_WHICH) - last_font = i; - - if (last_fore >= 0 && last_back >= 0 && last_font >= 0) - break; - } - - // now figure out how many more we need - int16 count = 0; - if (fFcs[last_fore].fColor != fore) - ++count; - if (fFcs[last_back].fColor != back) - ++count; - if (fFcs[last_font].fColor != font) - ++count; - - if (count) { - FontColor* new_fFcs; - new_fFcs = new FontColor[fFc_count + count]; - memcpy (new_fFcs, fFcs, fFc_count * sizeof (FontColor)); - delete [] fFcs; - fFcs = new_fFcs; - - if (fFcs[last_fore].fColor != fore) { - fFcs[fFc_count].fWhich = FORE_WHICH; - fFcs[fFc_count].fOffset = pos; - fFcs[fFc_count].fColor = fore; - ++fFc_count; - } - - if (fFcs[last_back].fColor != back) { - fFcs[fFc_count].fWhich = BACK_WHICH; - fFcs[fFc_count].fOffset = pos; - fFcs[fFc_count].fColor = back; - ++fFc_count; - } - - if (fFcs[last_font].fColor != font) { - fFcs[fFc_count].fWhich = FONT_WHICH; - fFcs[fFc_count].fOffset = pos; - fFcs[fFc_count].fColor = font; - ++fFc_count; - } - } - } else { - fFcs = new FontColor [fFc_count = 3]; - fFcs[0].fWhich = FORE_WHICH; - fFcs[0].fOffset = 0; - fFcs[0].fColor = fore; - fFcs[1].fWhich = BACK_WHICH; - fFcs[1].fOffset = 0; - fFcs[1].fColor = back; - fFcs[2].fWhich = FONT_WHICH; - fFcs[2].fOffset = 0; - fFcs[2].fColor = font; - } -} - - -void -Line::FigureEdges(Theme* theme, float width) -{ - delete [] fEdges; - fEdges = new float [fLength]; - - int cur_fFcs (0), next_fFcs (0), cur_font (0); - - fEdge_count = 0; - while (cur_fFcs < fFc_count) { - if (fFcs[cur_fFcs].fWhich == FONT_WHICH) { - cur_font = cur_fFcs; - break; - } - - ++cur_fFcs; - } - - while (cur_fFcs < fFc_count) { - int last_offset (fFcs[cur_fFcs].fOffset); - next_fFcs = cur_fFcs + 1; - - while (next_fFcs < fFc_count) { - // We want to break at every difference - // but, we want to break on a font if available - if (fFcs[next_fFcs].fOffset > last_offset) { - while (next_fFcs < fFc_count - && fFcs[next_fFcs].fWhich != FONT_WHICH - && next_fFcs + 1 < fFc_count - && fFcs[next_fFcs + 1].fOffset == fFcs[next_fFcs].fOffset) - ++next_fFcs; - - break; - } - ++next_fFcs; - } - - if (fFcs[cur_fFcs].fWhich == FONT_WHICH) - cur_font = cur_fFcs; - - int ccount; - int seglen; - - if (next_fFcs == fFc_count) { - ccount = CountChars (fFcs[cur_fFcs].fOffset, fLength - fFcs[cur_fFcs].fOffset); - seglen = fLength - fFcs[cur_fFcs].fOffset; - } else { - ccount = CountChars ( - fFcs[cur_fFcs].fOffset, - fFcs[next_fFcs].fOffset - fFcs[cur_fFcs].fOffset); - seglen = fFcs[next_fFcs].fOffset - fFcs[cur_fFcs].fOffset; - } - - // const BFont &f (theme->FontAt (fFcs[cur_font].fIndex)) - TextRender* tr = theme->TextRenderAt (fFcs[cur_font].fIndex); - -#ifdef __INTEL__ - float eshift[ccount]; -#else - float* eshift = new float[ccount]; -#endif - - /* f.GetEscapements ( - fText + fFcs[cur_fFcs].fOffset, - ccount, - eshift);*/ - - // if(tr) - tr->GetEscapements ( - fText + fFcs[cur_fFcs].fOffset, - ccount, - eshift); - - // This is not perfect, because we are including the left edge, - // but BFont::GetEdges doesn't seem to work as we'd like - - int i; - float size = 0; - - // if(tr) - size = tr->Size(); - - - float incrementor = (fEdge_count > 0) ? fEdges[fEdge_count - 1] : 0; - - for (i = 0; i < ccount; ++i) { - incrementor += (float)eshift[i] * size; - - fEdges[fEdge_count+i] = incrementor; - - // this little backfTracking routine is necessary in the case where an fFcs change - // comes immediately after a UTF8-char, since all but the first edge will be 0 - // and thus the new edge's starting position will be thrown off if we don't - // backtrack to the beginning of the char - if ((fEdge_count + i > 0) && fEdges[fEdge_count + i - 1] == 0) { - int32 temp = fEdge_count + i - 1; - while (fEdges[--temp] == 0); - fEdges[fEdge_count + i] += fEdges[temp]; - } - } - - for (i = fFcs[cur_fFcs].fOffset; i < fFcs[cur_fFcs].fOffset + seglen;) { - int len (UTF8_CHAR_LEN (fText[i]) - 1); - - if (len) { - int k; - for (k = fEdge_count + ccount - 1; k > i; --k) - fEdges[k + len] = fEdges[k]; - - for (k = 1; k <= len; ++k) - fEdges[i + k] = 0; - - ccount += len; - } - - i += len + 1; - } - - cur_fFcs = next_fFcs; - fEdge_count += ccount; -#ifndef __INTEL__ - delete [] eshift; -#endif - } - - SoftBreaks (theme, width); -} - - -void -Line::AddSoftBreak(SoftBreakEnd sbe, float& start, int& fText_place, - int16& font, float& width, float& start_width, Theme* theme) -{ - fText_place = (int)sbe.fOffset; - - if (fSoftie_size < fSoftie_used + 1) { - SoftBreak* new_softies; - - new_softies = new SoftBreak [fSoftie_size += SOFTBREAK_STEP]; - - if (fSofties) { - memcpy (new_softies, fSofties, sizeof (SoftBreak) * fSoftie_used); - delete [] fSofties; - } - - fSofties = new_softies; - } - - // consume whitespace - while (fText_place + 1 < fLength - && isspace (fText[fText_place + 1])) - ++fText_place; - - fSofties[fSoftie_used].fOffset = fText_place; - fSofties[fSoftie_used].fHeight = 0.0; - fSofties[fSoftie_used].fAscent = 0.0; - - int16 last (font); - while (font < fFc_count) { - TextRender* tr = theme->TextRenderAt (fFcs[font].fIndex); - - font_height fh; - float height; - - tr->GetHeight (&fh); - - height = (float)ceil (fh.ascent + fh.descent + fh.leading); - if (fSofties[fSoftie_used].fHeight < height) - fSofties[fSoftie_used].fHeight = height; - if (fSofties[fSoftie_used].fAscent < fh.ascent) - fSofties[fSoftie_used].fAscent = fh.ascent; - - // now try and find next - while (++font < fFc_count) - if (fFcs[font].fWhich == FONT_WHICH) - break; - - if (font == fFc_count - || fFcs[font].fOffset > fText_place) { - font = last; - break; - } - - last = font; - } - - if (fText_place < fLength) - start = fEdges[fText_place]; - - fBottom += fSofties[fSoftie_used++].fHeight; - fText_place += UTF8_CHAR_LEN (fText[fText_place]); - width = start_width - (theme->SoftLineIndent()); -} - - -void -Line::SoftBreaks(Theme* theme, float start_width) -{ - float margin = theme->TextMargin(); - float width = start_width; - float start = 0.0; - int fText_place = 0; - int space_place = 0; - int16 font (0); - - fSoftie_used = 0; - fBottom = fTop; - - // find first font - while (font < fFc_count && fFcs[font].fWhich != FONT_WHICH) - ++font; - - while (fText_place < fLength) { - while (space_place < fSpace_count) { - if (fEdges[(int)fSpaces[space_place]] - start > width) - break; - - ++space_place; - } - - // we've reached the end of the line (but it might not all fit) - // or we only have one space, so we check if we need to split the word - if (space_place == fSpace_count - || space_place == 0 - || fSpaces[space_place - 1] < fText_place) { - // everything fits.. how wonderful (but we want at least one softbreak) - if (fEdge_count == 0) { - AddSoftBreak((SoftBreakEnd(fLength - 1)), start, fText_place, font, width, start_width, theme); - break; - } - - int i (fEdge_count - 1); - - while (fEdges[i] == 0) - --i; - - if (fEdges[i] - start <= width) { - AddSoftBreak (SoftBreakEnd(fLength - 1), start, fText_place, font, width, start_width, theme); - continue; - } - - // we force at least one character - // your font may be a little too large for your window! - fText_place += UTF8_CHAR_LEN (fText[fText_place]); - while (fText_place < fLength) { - if (fEdges[fText_place] - start > width - margin) - break; - - fText_place += UTF8_CHAR_LEN (fText[fText_place]); - } - AddSoftBreak (SoftBreakEnd(fText_place), start, - fText_place, font, width, start_width, theme); - continue; - } - - // we encountered more than one space, so we rule out having to - // split the word, if the current word will fit within the bounds - int ccount1, ccount2; - --space_place; - - ccount1 = (int)fSpaces[space_place]; - ccount2 = (int)fSpaces[space_place+1] - ccount1; - - int i = ccount1 - 1; - while (fEdges[i] == 0) - --i; - - if (fEdges[ccount1 + ccount2] - fEdges[i] < width - margin) { - AddSoftBreak(SoftBreakEnd(fSpaces[space_place]), start, - fText_place, font, width, start_width, theme); - continue; - } - - // We need to break up the really long word - fText_place = fSpaces[space_place]; - while (fText_place < fEdge_count) { - if ((fEdges[fText_place] - start) > width) - break; - - fText_place += UTF8_CHAR_LEN (fText[fText_place]); - } - } - - fBottom -= 1; -} - - -int -Line::CountChars(int pos, int len) -{ - int ccount (0); - - if (pos >= fLength) - return ccount; - - if (pos + len > fLength) - len = fLength - pos; - - register int i = pos; - while (i < pos + len) { - i += UTF8_CHAR_LEN(fText[i]); - ++ccount; - } - - return ccount; -} - - -size_t -Line::SetStamp(const char* format, bool was_on) -{ - size_t size (0); - int32 i (0); - - if (was_on) { - int offset (fFcs[4].fOffset + 1); - - if (fUrls) { - for (i = 0; i < fUrls->CountItems(); i++) - fUrls->ItemAt(i)->fOffset -= offset; - } - memmove (fText, fText + offset, fLength - offset); - fText[fLength -= offset] = '\0'; - - for (i = 6; i < fFc_count; ++i) { - fFcs[i].fOffset -= offset; - fFcs[i - 6] = fFcs[i]; - } - - fFc_count -= 6; - } - - if (format) { - char buffer[1024]; - struct tm curTime; - - localtime_r(&fStamp, &curTime); - - // If no time specified, subsitute times with "x" - if (fStamp == 0) { - curTime.tm_hour, curTime.tm_min, curTime.tm_sec = 0; - BString newFormat(format); - newFormat.ReplaceAll("%H", "xx"); - - size = strftime(buffer, 1023, newFormat.String(), &curTime); - - const char* newBuffer = BString(buffer).ReplaceAll("0", "x").String(); - memcpy(buffer, newBuffer, size); - } - else - size = strftime (buffer, 1023, format, &curTime); - - if (fUrls) { - for (i = 0; i < fUrls->CountItems(); i++) - fUrls->ItemAt(i)->fOffset += size; - } - - char* new_fText; - new_fText = new char[fLength + size + 2]; - memcpy(new_fText, buffer, size); - new_fText[size++] = ' '; - new_fText[size] = '\0'; - - if (fText) { - memcpy (new_fText + size, fText, fLength); - delete [] fText; - } - - fText = new_fText; - fText[fLength += size] = '\0'; - - FontColor* new_fFcs; - new_fFcs = new FontColor [fFc_count + 6]; - - if (fFcs) { - memcpy ( - new_fFcs + 6, - fFcs, - fFc_count * sizeof (FontColor)); - delete [] fFcs; - } - fFcs = new_fFcs; - fFc_count += 6; - - fFcs[0].fWhich = FORE_WHICH; - fFcs[0].fColor = ui_color(B_LINK_HOVER_COLOR); - fFcs[0].fIndex = Theme::TimestampFore; - fFcs[0].fOffset = 0; - fFcs[1].fWhich = BACK_WHICH; - fFcs[1].fColor = ui_color(B_PANEL_BACKGROUND_COLOR); - fFcs[1].fIndex = Theme::TimestampBack; - fFcs[1].fOffset = 0; - fFcs[2].fWhich = FONT_WHICH; - fFcs[2].fColor = ui_color(B_PANEL_BACKGROUND_COLOR); - fFcs[2].fIndex = Theme::TimestampFont; - fFcs[2].fOffset = 0; - - fFcs[3].fWhich = FORE_WHICH; - fFcs[0].fColor = ui_color(B_LINK_HOVER_COLOR); - fFcs[3].fIndex = Theme::TimespaceFore; - fFcs[3].fOffset = size - 1; - fFcs[4].fWhich = BACK_WHICH; - fFcs[4].fColor = ui_color(B_PANEL_BACKGROUND_COLOR); - fFcs[4].fIndex = Theme::TimespaceBack; - fFcs[4].fOffset = size - 1; - fFcs[5].fWhich = FONT_WHICH; - fFcs[5].fColor = ui_color(B_PANEL_BACKGROUND_COLOR); - fFcs[5].fIndex = Theme::TimespaceFont; - fFcs[5].fOffset = size - 1; - - for (i = 6; i < fFc_count; ++i) - fFcs[i].fOffset += size; - } - - return size; -} - - -void -Line::SelectWord(int* start, int* end) -{ - int start_tmp (*start), end_tmp (*end); - - while (start_tmp > 0 && fText[start_tmp-1] != ' ') - start_tmp--; - - while ((end_tmp - 1) < fLength && fText[end_tmp] != ' ') - end_tmp++; - - while (end_tmp >= fLength) - --end_tmp; - - *start = start_tmp; - *end = end_tmp; -} - - diff --git a/libs/librunview/RunView.h b/libs/librunview/RunView.h index 02b7069..c376759 100644 --- a/libs/librunview/RunView.h +++ b/libs/librunview/RunView.h @@ -1,187 +1,24 @@ /* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (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 Vision. - * - * The Initial Developer of the Original Code is The Vision Team. - * Portions created by The Vision Team are - * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights - * Reserved. - * - * Contributor(s): Rene Gollent - * Todd Lair + * Copyright 2021, Jaidyn Levesque + * All rights reserved. Distributed under the terms of the MIT license. */ +#ifndef _RUN_VIEW_H +#define _RUN_VIEW_H -#ifndef RUNVIEW_H_ -#define RUNVIEW_H_ +#include -#define LINE_COUNT 1000 -#include - -const uint32 M_LOOKUP_WEBSTER = 'rvlw'; -const uint32 M_LOOKUP_GOOGLE = 'rvlg'; -const uint32 M_LOOKUP_ACRONYM = 'rvla'; -const uint32 M_CLEAR = 'rvcl'; - -const uint32 M_OFFVIEW_SELECTION = 'rvos'; -const uint32 M_THEME_FOREGROUND_CHANGE = 'rvtf'; -const uint32 M_THEME_BACKGROUND_CHANGE = 'rvtb'; -const uint32 M_THEME_FONT_CHANGE = 'rvto'; - -#define C_URL 0 -#define F_URL 0 - -struct Line; -class Theme; -class RunView; -class BScrollView; -class BCursor; -class BMessageRunner; -class BPopUpMenu; - -class SelectPos -{ +class RunView : public BTextView { public: + RunView(const char* name); - int fLine; - int fOffset; - - SelectPos ( - int selLine = 0, - int selOffset = 0) - : fLine (selLine), - fOffset (selOffset) - { } - - SelectPos (const SelectPos& pos) - : fLine (pos.fLine), - fOffset (pos.fOffset) - { } - - ~SelectPos (void) - { } - - SelectPos& operator = (const SelectPos& pos) { - fLine = pos.fLine; - fOffset = pos.fOffset; - - return *this; - } - - inline int operator == (const SelectPos& rhs) const { - return ((fLine == rhs.fLine) && (fOffset == rhs.fOffset)); - } - - inline int operator != (const SelectPos& rhs) const { - return (!(*this == rhs)); - } - + void Append(const char* text, rgb_color color, + uint16 fontFace = B_REGULAR_FACE); + void Append(const char* text); +private: + bool fLastStyled; + text_run_array fDefaultRun; }; -class RunView : public BView -{ - BScrollView* fScroller; - BCursor* fURLCursor; - Theme* fTheme; - - Line* fWorking; - Line* fLines[LINE_COUNT]; - int16 fLine_count, - fClickCount; - - char* fStamp_format; - char* fClipping_name; - - SelectPos fSp_start, fSp_end; - - int32 fTracking; - SelectPos fTrack_offset; - BMessageRunner* fOff_view_runner; - bigtime_t fOff_view_time; - - bool fResizedirty; - bool fFontsdirty; - BPopUpMenu* fMyPopUp; - BPoint fLastClick; - bigtime_t fLastClickTime; - - - bool RecalcScrollBar (bool constrain); - void ResizeRecalc (void); - void FontChangeRecalc (void); - void ExtendTrackingSelect (BPoint); - void ShiftTrackingSelect (BPoint, bool, bigtime_t); - void CheckURLCursor (BPoint); - void BuildPopUp (void); - - bool CheckClickBounds (const SelectPos&, - const BPoint&) const; - void LoadURL(const char* url); - -public: - - RunView ( - BRect, - const char*, - Theme*, - uint32 = B_FOLLOW_LEFT | B_FOLLOW_TOP, - uint32 = 0UL); - virtual ~RunView (void); - - virtual void AttachedToWindow (void); - virtual void DetachedFromWindow (void); - virtual void FrameResized (float, float); - virtual void TargetedByScrollView (BScrollView*); - virtual void Show (); - virtual void Draw (BRect); - virtual void MessageReceived (BMessage*); - - virtual void SetViewColor (rgb_color); - void SetViewColor (uchar red, uchar green, uchar blue, uchar alpha = 255) { - rgb_color color = {red, green, blue, alpha}; - SetViewColor (color); - } - - - virtual void MouseDown (BPoint); - virtual void MouseMoved (BPoint, uint32, const BMessage*); - virtual void MouseUp (BPoint); - - - void Append (const char*, int32, rgb_color, rgb_color, rgb_color, time_t = 0); - void Append (const char*, rgb_color, rgb_color, rgb_color, time_t = 0); - - void Clear (void); - - int16 LineCount (void) const; - const char* LineAt (int) const; - - void SetTimeStampFormat (const char*); - void SetTheme (Theme*); - - SelectPos PositionAt (BPoint) const; - BPoint PointAt (SelectPos) const; - - BRect GetTextFrame (const SelectPos&, const SelectPos&) const; - bool IntersectSelection (const SelectPos&, const SelectPos&) const; - void GetSelectionText (BString&) const; - void Select (const SelectPos&, const SelectPos&); - void SelectAll (void); - void SetClippingName (const char*); - bool FindText(const char*); - - void ScrollToBottom(void); - void ScrollToSelection(void); -}; - -#endif +#endif // _RUN_VIEW_H diff --git a/libs/librunview/SmileTextRender.h b/libs/librunview/SmileTextRender.h deleted file mode 100644 index 2930ac2..0000000 --- a/libs/librunview/SmileTextRender.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef _SmileTextRender_H_ -#define _SmileTextRender_H_ - -#include -#include - -#include -#include -#include -#include - -#include -#include - - -class SmileTextRender : public TextRender -{ -public: - - SmileTextRender(): TextRender() {}; - - virtual ~SmileTextRender() {}; - - virtual void Render(BView* target, const char* txt, int num, BPoint pos) { - - BBitmap* pointer = NULL; - BString f(txt, num); - - if (Emoticor::Get()->Config()->FindPointer(f.String(), (void**)&pointer) == B_OK) { - target->SetDrawingMode( B_OP_ALPHA ); - target->DrawBitmapAsync( pointer, BPoint(pos.x, pos.y - (Emoticor::Get()->Config()->GetEmoticonSize() / 2)) ); - target->SetDrawingMode( B_OP_OVER ); - } - }; - - - virtual float Size() { - printf("GETTING EMOTICOR SIZE!!!!\n"); - return Emoticor::Get()->Config()->GetEmoticonSize(); - } - - virtual void GetHeight(font_height* h) { - h->descent = h->ascent = Emoticor::Get()->Config()->GetEmoticonSize() / 2; - h->leading = 0; - }; - - virtual void - GetEscapements(const char * /*charArray*/, int32 numChars, float escapementArray[]) { - //font.GetEscapements(charArray,numChars,escapementArray); - escapementArray[0] = 1; - for (int i = 1; i < numChars; i++) escapementArray[i] = 0; - } -}; -#endif diff --git a/libs/librunview/TextRender.h b/libs/librunview/TextRender.h deleted file mode 100644 index d47d4e5..0000000 --- a/libs/librunview/TextRender.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _TextRender_H_ -#define _TextRender_H_ - -#include - -class TextRender -{ -public: - TextRender() {}; - virtual ~TextRender() {}; - - virtual void Render(BView* target, const char*, int num, BPoint pos) = 0; - virtual void GetHeight(font_height* height) = 0; - virtual void GetEscapements(const char charArray[], int32 numChars, float escapementArray[]) = 0; - virtual float Size() = 0; - // - -}; -#endif diff --git a/libs/librunview/Theme.cpp b/libs/librunview/Theme.cpp deleted file mode 100644 index 01ef5d0..0000000 --- a/libs/librunview/Theme.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (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 Vision. - * - * The Initial Developer of the Original Code is The Vision Team. - * Portions created by The Vision Team are - * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights - * Reserved. - * - * Contributor(s): Rene Gollent - * Todd Lair - * Andrea Anzani, andrea.anzani@gmail.com - */ - -#define NUMBER_THEME_READERS 1000 - -#include -#include -#include -#include -#include //fix -#include - -#include "Theme.h" -#include "NormalTextRender.h" - -int Theme::TimestampFore = 0; -int Theme::TimestampBack = 0; -int Theme::TimestampFont = 0; -int Theme::TimespaceFore = 1; -int Theme::TimespaceBack = 1; -int Theme::TimespaceFont = 1; -int Theme::NormalFore = 2; -int Theme::NormalBack = 2; -int Theme::NormalFont = 2; -int Theme::SelectionBack = 3; - -//at least we use a 'normal' text render - - -Theme::Theme(const char* n, int foreCount, int backCount, int renderCount) - : - name (NULL), - fores (NULL), - backs (NULL), - text_renders (NULL), - fore_count (max_c (foreCount, 4)), - back_count (max_c (backCount, 4)), - render_count (max_c (renderCount, 4)) -{ - - fSoftLineIndent = (float)(MARGIN_WIDTH / 2.0); - fTextMargin = (float)(MARGIN_WIDTH / 2.0); - - name = strcpy (new char [strlen (n) + 1], n); - - fores = new rgb_color [fore_count]; - backs = new rgb_color [back_count]; - - normal_textrender = new NormalTextRender(be_plain_font); - - text_renders = (TextRender**)malloc(render_count * sizeof(TextRender*)); - for ( int i = 0; i < render_count; i++ ) - text_renders[i] = normal_textrender; - - - - sid = create_sem (NUMBER_THEME_READERS, name); - - rgb_color def_timestamp_fore = {200, 150, 150, 255}; - rgb_color def_timestamp_back = {255, 255, 255, 255}; - rgb_color def_fore = {0, 0, 0, 255}; - rgb_color def_back = {255, 255, 255, 255}; - - fores[0] = def_timestamp_fore; - - int i; - for (i = 1; i < fore_count; ++i) - fores[i] = def_fore; - - backs[0] = def_timestamp_back; - for (i = 1; i < back_count; ++i) - backs[i] = def_back; -} - - -Theme::~Theme (void) -{ - delete_sem (sid); - - //delete [] fonts; - for ( int i = 0; i < render_count; i++ ) - if ( text_renders[i] ) - text_renders[i] = NULL; - - delete normal_textrender; - - delete [] backs; - delete [] fores; - delete [] name; -} - - -int -Theme::CountForegrounds (void) const -{ - return fore_count; -} - - -int -Theme::CountBackgrounds (void) const -{ - return back_count; -} -/* -int16 -Theme::CountFonts (void) const -{ - return font_count; -} -*/ - - -int -Theme::CountTextRenders (void) const -{ - return render_count; -} - - -void -Theme::ReadLock (void) -{ - acquire_sem (sid); -} - - -void -Theme::ReadUnlock (void) -{ - release_sem (sid); -} - - -void -Theme::WriteLock (void) -{ - acquire_sem_etc (sid, NUMBER_THEME_READERS, 0, 0); -} - - -void -Theme::WriteUnlock (void) -{ - release_sem_etc (sid, NUMBER_THEME_READERS, 0); -} - - -const rgb_color -Theme::ForegroundAt (int which) const -{ - rgb_color color = {0, 0, 0, 255}; - - if (which >= fore_count || which < 0) - return color; - - return fores[which]; -} - - -const rgb_color -Theme::BackgroundAt (int which) const -{ - rgb_color color = {255, 255, 255, 255}; - - if (which >= back_count || which < 0) - return color; - - return backs[which]; -} -/* -const BFont & -Theme::FontAt (int16 which) const -{ - if (which >= font_count || which < 0) - return *be_plain_font; - - return fonts[which]; -} -*/ - - -TextRender* -Theme::TextRenderAt (int which) -{ - if ( which < 0 ) { - //printf("Theme::TextRenderAt(): which < 0 (%d)\n", which); - return normal_textrender; - } - if ( which >= render_count ) { - //printf("Theme::TextRenderAt(): which >= render_count (%d, %d)\n", which, render_count); - return normal_textrender; - } - - return text_renders[which]; -} - - -bool -Theme::SetForeground (int which, const rgb_color color) -{ - if (which >= fore_count || which < 0) - return false; - - fores[which] = color; - return true; -} - - -bool -Theme::SetBackground (int which, const rgb_color color) -{ - if (which >= back_count || which < 0) - return false; - - backs[which] = color; - return true; -} - - -bool -Theme::SetTextRender(int which, TextRender* trender) -{ - - - if (which >= render_count || which < 0 || !trender) - return false; - - text_renders[which] = trender; - return true; -} - - -void -Theme::AddView (BView* view) -{ - list.AddItem (view); -} - - -void -Theme::RemoveView (BView* view) -{ - list.RemoveItem (view); -} - - -void -Theme::SetTextMargin(float margin) -{ - fTextMargin = margin; -} - - -void -Theme::SetSoftLineIndent(float indent) -{ - fSoftLineIndent = indent; -} diff --git a/libs/librunview/Theme.h b/libs/librunview/Theme.h deleted file mode 100644 index 55bcee6..0000000 --- a/libs/librunview/Theme.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (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 Vision. - * - * The Initial Developer of the Original Code is The Vision Team. - * Portions created by The Vision Team are - * Copyright (C) 1999, 2000, 2001 The Vision Team. All Rights - * Reserved. - * - * Contributor(s): Rene Gollent - * Todd Lair - */ - -#ifndef THEME_H_ -#define THEME_H_ - -#include -#include -#include - -#include - -class BView; -class NormalTextRender; - -#define MARGIN_WIDTH 10.0 //default value, double of fTextMargin -#define MARGIN_INDENT 10.0 //default value, double of fSoftLineIndent - -class Theme -{ - char* name; - rgb_color* fores; - rgb_color* backs; - TextRender** text_renders; //FIX!! - - int fore_count; - int back_count; - int render_count; - - BList list; - sem_id sid; - - float fSoftLineIndent; - float fTextMargin; - NormalTextRender* normal_textrender; - -public: - - static int TimestampFore; - static int TimestampBack; - static int TimestampFont; - static int TimespaceFore; - static int TimespaceBack; - static int TimespaceFont; - static int NormalFore; - static int NormalBack; - static int NormalFont; - static int SelectionBack; - - Theme(const char*, int, int, int); - virtual ~Theme (void); - - const char* Name (void) const { - return name; - } - - void ReadLock (void); - void ReadUnlock (void); - void WriteLock (void); - void WriteUnlock (void); - - int CountForegrounds (void) const; - int CountBackgrounds (void) const; - // int16 CountFonts (void) const; - int CountTextRenders (void) const; - - const rgb_color ForegroundAt (int) const; - const rgb_color BackgroundAt (int) const; - - //const BFont &FontAt (int16) const; - - TextRender* TextRenderAt(int); - - bool SetForeground (int, const rgb_color); - bool SetForeground (int w, uchar r, uchar g, uchar b, uchar a = 255) { - rgb_color color = {r, g, b, a}; - return SetForeground (w, color); - } - bool SetBackground (int, const rgb_color); - bool SetBackground (int w, uchar r, uchar g, uchar b, uchar a = 255) { - rgb_color color = {r, g, b, a}; - return SetBackground (w, color); - } - - //bool SetFont (int16, const BFont &); - bool SetTextRender(int, TextRender*); - - void SetSoftLineIndent(float indent); - void SetTextMargin(float margin); - - float TextMargin() const { - return fTextMargin; - } - float SoftLineIndent() const { - return fSoftLineIndent; - } - - - - void AddView (BView*); - void RemoveView (BView*); - - -}; - -#endif