diff --git a/libs/librunview/RunView.cpp b/libs/librunview/RunView.cpp index 4497151..4da7c83 100644 --- a/libs/librunview/RunView.cpp +++ b/libs/librunview/RunView.cpp @@ -6,9 +6,16 @@ #include "RunView.h" #include +#include +#include +#include #include +const uint32 kSearchDdg = 'RVse'; +const uint32 kSearchDict = 'RVdc'; + + RunView::RunView(const char* name) : BTextView(name), @@ -33,26 +40,45 @@ RunView::RunView(const char* name) void -RunView::Append(const char* text, rgb_color color, uint16 fontFace) +RunView::MessageReceived(BMessage* msg) { - BFont font; - font.SetFace(fontFace); - text_run run = { 0, font, color }; - text_run_array array = { 1, {run} }; + switch (msg->what) + { + case kSearchDdg: + case kSearchDict: + { + int32 start = 0; + int32 end = 0; + GetSelection(&start, &end); + if (start == end) + break; + char* buffer = new char[end - start]; + GetText(start, end - start, buffer); - Insert(text, &array); - fLastStyled = true; -} + // Build query + BString query; + if (msg->what == kSearchDict) + query = "https://%lang%.wiktionary.org/w/index.php?search=%q%"; + else + query = "https://duckduckgo.com/?q=%q%"; + BLanguage lang; + if (BLocale().GetLanguage(&lang) == B_OK) + query.ReplaceAll("%lang%", lang.Code()); + else + query.ReplaceAll("%lang", "eo"); -void -RunView::Append(const char* text) -{ - if (fLastStyled == false) - Insert(text); - else - Insert(text, &fDefaultRun); - fLastStyled = false; + query.ReplaceAll("%q%", BUrl::UrlEncode(BString(buffer))); + + // Send query + BUrl url(query.String()); + if (url.IsValid()) + url.OpenWithPreferredApplication(true); + break; + } + default: + BTextView::MessageReceived(msg); + } } @@ -100,7 +126,9 @@ RunView::MouseDown(BPoint where) uint32 buttons = 0; Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); - if (!(buttons & B_SECONDARY_MOUSE_BUTTON)) + if (buttons & B_SECONDARY_MOUSE_BUTTON) + _RightClickPopUp(where)->Go(ConvertToScreen(where), true, false); + else BTextView::MouseDown(where); BUrl url; @@ -150,26 +178,63 @@ RunView::Select(int32 startOffset, int32 endOffset) } +void +RunView::Append(const char* text, rgb_color color, uint16 fontFace) +{ + BFont font; + font.SetFace(fontFace); + text_run run = { 0, font, color }; + text_run_array array = { 1, {run} }; + + Insert(text, &array); + fLastStyled = true; +} + + +void +RunView::Append(const char* text) +{ + if (fLastStyled == false) + Insert(text); + else + Insert(text, &fDefaultRun); + fLastStyled = false; +} + + BString RunView::WordAt(BPoint point) { - int32 wordOffset = OffsetAt(point); - int32 lineOffset = OffsetAt(LineAt(point)); - const char* lineBuff = GetLine(LineAt(point)); + int32 start = 0; + int32 end = 0; + BString word; + + FindWordAround(OffsetAt(point), &start, &end, &word); + return word; +} + + +void +RunView::FindWordAround(int32 offset, int32* start, int32* end, BString* _word) +{ + int32 lineOffset = OffsetAt(LineAt(offset)); + const char* lineBuff = GetLine(LineAt(offset)); BString line(lineBuff); delete lineBuff; - int32 wordStart = line.FindLast(" ", wordOffset - lineOffset) + 1; - int32 wordEnd = line.FindFirst(" ", wordOffset - lineOffset); + int32 wordStart = line.FindLast(" ", offset - lineOffset) + 1; + int32 wordEnd = line.FindFirst(" ", offset - lineOffset); if (wordStart == B_ERROR) wordStart = 0; if (wordEnd == B_ERROR) wordEnd = line.CountChars(); - BString buffer; - line.CopyCharsInto(buffer, wordStart, wordEnd - wordStart); - return buffer; + *start = lineOffset + wordStart; + *end = lineOffset + wordEnd; + + if (_word != NULL) + line.CopyCharsInto(*_word, wordStart, wordEnd - wordStart); } @@ -220,3 +285,41 @@ RunView::ScrollToBottom() { ScrollToOffset(TextLength()); } + + +BPopUpMenu* +RunView::_RightClickPopUp(BPoint where) +{ + BPopUpMenu* menu = new BPopUpMenu("rightClickPopUp"); + BMenuItem* ddgSearch = + new BMenuItem("Search" B_UTF8_ELLIPSIS, new BMessage(kSearchDdg)); + BMenuItem* dictSearch = + new BMenuItem("Dictionary" B_UTF8_ELLIPSIS, new BMessage(kSearchDict)); + BMenuItem* copy = + new BMenuItem("Copy", new BMessage(B_COPY), 'C', B_COMMAND_KEY); + BMenuItem* selectAll = new BMenuItem("Select all", + new BMessage(B_SELECT_ALL), 'A', B_COMMAND_KEY); + + // Try and ensure we have something selected + int32 start = 0; + int32 end = 0; + GetSelection(&start, &end); + + if (start == end && OverText(where) == true) { + start = 0; + end = 0; + FindWordAround(OffsetAt(where), &start, &end); + Select(start, end); + } + copy->SetEnabled(start < end); + dictSearch->SetEnabled(start < end); + ddgSearch->SetEnabled(start < end); + + menu->AddItem(ddgSearch); + menu->AddItem(dictSearch); + menu->AddSeparatorItem(); + menu->AddItem(copy); + menu->AddItem(selectAll); + menu->SetTargetForItems(this); + return menu; +} diff --git a/libs/librunview/RunView.h b/libs/librunview/RunView.h index 8eb14f4..aa381df 100644 --- a/libs/librunview/RunView.h +++ b/libs/librunview/RunView.h @@ -8,14 +8,14 @@ #include #include +class BPopUpMenu; + class RunView : public BTextView { public: RunView(const char* name); - void Append(const char* text, rgb_color color, - uint16 fontFace = B_REGULAR_FACE); - void Append(const char* text); + virtual void MessageReceived(BMessage* msg); // Only differs in that it changes font face and color of any URLs virtual void Insert(const char* text, const text_run_array* runs = NULL); @@ -26,7 +26,13 @@ public: virtual void Select(int32 startOffset, int32 endOffset); + void Append(const char* text, rgb_color color, + uint16 fontFace = B_REGULAR_FACE); + void Append(const char* text); + BString WordAt(BPoint point); + void FindWordAround(int32 offset, int32* start, int32* end, + BString* _word = NULL); const char* GetLine(int32 line); bool OverText(BPoint where); @@ -35,6 +41,8 @@ public: void ScrollToBottom(); private: + BPopUpMenu* _RightClickPopUp(BPoint where); + bool fLastStyled; text_run_array fDefaultRun; text_run_array fUrlRun; diff --git a/libs/librunview/Utilities.cpp b/libs/librunview/Utilities.cpp deleted file mode 100644 index c38eebf..0000000 --- a/libs/librunview/Utilities.cpp +++ /dev/null @@ -1,367 +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): Wade Majors - * Todd Lair - * Andrew Bazan - */ - -#include -#include - -#include -#include -#include -#include -#include - -const float doubleClickThresh = 6; - -BString -GetWord (const char* cData, int32 wordNeeded) -{ - /* - * Function purpose: Get word number {wordNeeded} from {cData} - * (space delimited) - */ - - BString data (cData); - BString buffer ("-9z99"); - int32 wordAt (1), place (0); - - while (wordAt != wordNeeded && place != B_ERROR) { - if ((place = data.FindFirst ('\x20', place)) != B_ERROR) - if (++place < data.Length() - && data[place] != '\x20') - ++wordAt; - } - - if (wordAt == wordNeeded - && place != B_ERROR - && place < data.Length()) { - int32 end (data.FindFirst ('\x20', place)); - - if (end == B_ERROR) - end = data.Length(); - - data.CopyInto (buffer, place, end - place); - } - - return buffer; -} - -BString -GetWordColon (const char* cData, int32 wordNeeded) -{ - /* - * Function purpose: Get word number {wordNeeded} from {cData} - * (colon delimited) - */ - - BString data (cData); - BString buffer ("-9z99"); - int32 wordAt (1), place (0); - - while (wordAt != wordNeeded && place != B_ERROR) { - if ((place = data.FindFirst (':', place)) != B_ERROR) - if (++place < data.Length() - && data[place] != ':') - ++wordAt; - } - - if (wordAt == wordNeeded - && place != B_ERROR - && place < data.Length()) { - int32 end (data.FindFirst (':', place)); - - if (end == B_ERROR) - end = data.Length(); - - data.CopyInto (buffer, place, end - place); - } - - return buffer; -} - -BString -RestOfString (const char* cData, int32 wordStart) -{ - /* - * Function purpose: Get word number {wordStart} from {cData} - * append the rest of the string after {wordStart} - * (space delimited) - */ - - BString data (cData); - int32 wordAt (1), place (0); - BString buffer ("-9z99"); - - while (wordAt != wordStart && place != B_ERROR) { - if ((place = data.FindFirst ('\x20', place)) != B_ERROR) - if (++place < data.Length() - && data[place] != '\x20') - ++wordAt; - } - - if (wordAt == wordStart - && place != B_ERROR - && place < data.Length()) - data.CopyInto (buffer, place, data.Length() - place); - - return buffer; -} - -BString -GetNick (const char* cData) -{ - /* - * Function purpose: Get nickname from {cData} - * - * Expected format: nickname!user@host.name - */ - - BString data (cData); - BString theNick; - - for (int32 i = 1; i < data.Length() && data[i] != '!' && data[i] != '\x20'; ++i) - theNick += data[i]; - - return theNick; -} - -BString -GetIdent (const char* cData) -{ - /* - * Function purpose: Get identname/username from {cData} - * - * Expected format: nickname!user@host.name - */ - - BString data (GetWord(cData, 1)); - BString theIdent; - int32 place[2]; - - if ((place[0] = data.FindFirst ('!')) != B_ERROR - && (place[1] = data.FindFirst ('@')) != B_ERROR) { - ++(place[0]); - data.CopyInto (theIdent, place[0], place[1] - place[0]); - } - - return theIdent; -} - -BString -GetAddress (const char* cData) -{ - /* - * Function purpose: Get address/hostname from {cData} - * - * Expected format: nickname!user@host.name - */ - - BString data (GetWord(cData, 1)); - BString address; - int32 place; - - if ((place = data.FindFirst ('@')) != B_ERROR) { - int32 length (data.FindFirst ('\x20', place)); - - if (length == B_ERROR) - length = data.Length(); - - ++place; - data.CopyInto (address, place, length - place); - } - - return address; -} - -BString -TimeStamp() -{ - /* - * Function purpose: Return the timestamp string - * - */ - - // if(!vision_app->GetBool ("timestamp")) - // return ""; - - // const char *ts_format (vision_app->GetString ("timestamp_format")); - const char* ts_format = "[%H:%M]"; - - time_t myTime (time (0)); - tm curTime; - localtime_r (&myTime, &curTime); - - char tempTime[32]; - tempTime[strftime (tempTime, 31, ts_format, &curTime)] = '\0'; - - return BString (tempTime).Append('\x20', 1); -} - - -BString -ExpandKeyed ( - const char* incoming, - const char* keys, - const char** expansions) -{ - BString buffer; - - while (incoming && *incoming) { - if (*incoming == '$') { - const char* place; - - ++incoming; - - if ((place = strchr (keys, *incoming)) != 0) - buffer += expansions[place - keys]; - else - buffer += *incoming; - } else - buffer += *incoming; - - ++incoming; - } - - buffer += "\n"; - - return buffer; -} - -BString -StringToURI (const char* string) -{ - /* - * Function purpose: Converts {string} to a URI safe format - * - */ - - BString buffer (string); - buffer.ToLower(); - buffer.ReplaceAll ("%", "%25"); // do this first! - buffer.ReplaceAll ("\n", "%20"); - buffer.ReplaceAll (" ", "%20"); - buffer.ReplaceAll ("\"", "%22"); - buffer.ReplaceAll ("#", "%23"); - buffer.ReplaceAll ("@", "%40"); - buffer.ReplaceAll ("`", "%60"); - buffer.ReplaceAll (":", "%3A"); - buffer.ReplaceAll ("<", "%3C"); - buffer.ReplaceAll (">", "%3E"); - buffer.ReplaceAll ("[", "%5B"); - buffer.ReplaceAll ("\\", "%5C"); - buffer.ReplaceAll ("]", "%5D"); - buffer.ReplaceAll ("^", "%5E"); - buffer.ReplaceAll ("{", "%7B"); - buffer.ReplaceAll ("|", "%7C"); - buffer.ReplaceAll ("}", "%7D"); - buffer.ReplaceAll ("~", "%7E"); - return buffer; -} - -BString -DurationString (int64 value) -{ - /* - * Function purpose: Return a duration string based on {value} - * - */ - - BString duration; - bigtime_t micro = value; - bigtime_t milli = micro / 1000; - bigtime_t sec = milli / 1000; - bigtime_t min = sec / 60; - bigtime_t hours = min / 60; - bigtime_t days = hours / 24; - - char message[512] = ""; - if (days) - sprintf(message, "%Ld day%s ", days, days != 1 ? "s" : ""); - - if (hours % 24) - sprintf(message, "%s%Ld hr%s ", message, hours % 24, (hours % 24) != 1 ? "s" : ""); - - if (min % 60) - sprintf(message, "%s%Ld min%s ", message, min % 60, (min % 60) != 1 ? "s" : ""); - - sprintf(message, "%s%Ld.%Ld sec%s", message, sec % 60, (milli % 1000), (sec % 60) != 1 ? "s" : ""); - - duration += message; - - return duration; -} - - -const char * -RelToAbsPath (const char* append_) -{ - app_info ai; - be_app->GetAppInfo (&ai); - - BEntry entry (&ai.ref); - BPath path; - entry.GetPath (&path); - path.GetParent (&path); - path.Append (append_); - - return path.Path(); -} - - -int32 -Get440Len (const char* cData) -{ - BString data (cData); - - if (data.Length() < 440) - return data.Length(); - else { - int32 place (data.FindLast ('\x20', 440)); - if (place == B_ERROR) - return 440; - return place; - } -} - -uint16 -CheckClickCount(BPoint point, BPoint& lastClick, bigtime_t sysTime, bigtime_t& lastClickTime, int16& clickCount) -{ - // check time and proximity - BPoint delta = point - lastClick; - - bigtime_t timeDelta = sysTime - lastClickTime; - - bigtime_t doubleClickSpeed; - get_click_speed(&doubleClickSpeed); - - lastClickTime = sysTime; - - if (timeDelta < doubleClickSpeed - && fabs(delta.x) < doubleClickThresh - && fabs(delta.y) < doubleClickThresh) - return (++clickCount); - - lastClick = point; - clickCount = 1; - return clickCount; -} - diff --git a/libs/librunview/Utilities.h b/libs/librunview/Utilities.h deleted file mode 100644 index 0695d27..0000000 --- a/libs/librunview/Utilities.h +++ /dev/null @@ -1,68 +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): Wade Majors - * Todd Lair - * Andrew Bazan - */ - -#ifndef _UTILITIES_H -#define _UTILITIES_H_ - -#include - -template class AutoDestructor -{ -public: - AutoDestructor(T* t) { - fObject = t; - } - - virtual ~AutoDestructor(void) { - delete fObject; - } - - void SetTo(T* t) { - delete fObject; - fObject = t; - } - -private: - T* fObject; -}; - - -class BMessage; -class BPoint; - -BString GetWord (const char*, int32); -BString RestOfString (const char*, int32); -BString GetNick (const char*); -BString GetIdent (const char*); -BString GetAddress (const char*); -BString TimeStamp (void); -BString ExpandKeyed (const char*, const char*, const char**); -BString DurationString (int64); -BString StringToURI (const char*); -const char* RelToAbsPath (const char*); -BString GetWordColon (const char*, int32); -int32 Get440Len (const char*); -uint16 CheckClickCount(BPoint, BPoint&, bigtime_t, bigtime_t&, int16&); - - -#endif