Implement Find in Terminal. This is almost identical to R5's Terminal, except that it doesn't look for regexps. Code tested by me. Thanks to jburton for helping me out and reviewing the patch.

This resolves bug #199.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18561 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Niels Sascha Reedijk
2006-08-22 09:33:01 +00:00
parent 0adbde4a9e
commit f95dbf8906
12 changed files with 365 additions and 84 deletions
-3
View File
@@ -13,10 +13,7 @@ Stuff already done thats better than R5:
Terminal window supports scrolling
TODO:
Make a Jamfile
Make Find work
Fix titling (-t works already, its the Terminal 1, 2, 3, etc...)
Fix the Colour menu
Move Fonts and font sizes to the "Right Place"
Kill the Preferences Panel
Move to .rdef source resources
-42
View File
@@ -1,42 +0,0 @@
/*Terminal: constants*/
#ifndef CONSTANTS_H
#define CONSTANTS_H
#include <GraphicsDefs.h>
#include <SupportDefs.h>
#define APP_SIGNATURE "application/x-vnd.obos.terminal"
const float TEXT_INSET = 3.0;
// Application messages
const uint32 OPEN_TERMINAL ='OTRM';
// Messages for menu commands
// Terminal
const uint32 TERMINAL_SWITCH_TERMINAL ='TSWT';
const uint32 TERMINAL_START_NEW_TERMINAL='TSNT';
const uint32 TERMINAL_LOG_TO_FILE ='TLTF';
// Edit
const uint32 EDIT_WRITE_SELECTION ='EWSL';
const uint32 EDIT_CLEAR_ALL ='ECLA';
const uint32 EDIT_FIND ='EFND';
const uint32 EDIT_FIND_BACKWARD ='EFBK';
const uint32 EDIT_FIND_FORWARD ='EFFD';
// Settings
const uint32 SETTINGS_WINDOW_SIZE ='SWSZ';
const uint32 SETTINGS_FONT ='SFNT';
const uint32 SETTINGS_FONT_SIZE ='SFSZ';
const uint32 SETTINGS_FONT_ENCODING ='SFEN';
const uint32 SETTINGS_TAB_WIDTH ='STBW';
const uint32 SETTINGS_COLOR ='SCLR';
const uint32 SETTINGS_SAVE_AS_DEFAULT ='SSAD';
const uint32 SETTINGS_SAVE_AS_SETTINGS ='SSAS';
// Edit menu toggle
const uint32 ENABLE_ITEMS ='EDON';
const uint32 DISABLE_ITEMS ='EDOF';
#endif // CONSTANTS_H
+118 -19
View File
@@ -31,12 +31,16 @@
#include <Window.h>
#include <Rect.h>
#include <TextControl.h>
#include <Box.h>
#include <CheckBox.h>
#include <Button.h>
#include <RadioButton.h>
#include <Message.h>
#include <stdio.h>
#include <File.h>
#include <String.h>
#include "TermWindow.h"
#include "FindDlg.h"
#include "TermApp.h"
#include "MenuUtil.h"
@@ -44,34 +48,90 @@
// message define
const uint32 FPANEL_HIDE = 'Fhid';
const uint32 MSG_FIND_HIDE = 'Fhid';
//////////////////////////////////////////////////////////////////////////////
// FindDlg
// Constructer
//////////////////////////////////////////////////////////////////////////////
FindDlg::FindDlg (BRect frame, TermWindow *win)
: BWindow(frame, "Find",
B_FLOATING_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
: BWindow(frame, "Find",
B_FLOATING_WINDOW, B_NOT_RESIZABLE|B_NOT_ZOOMABLE)
{
PrefHandler title;
LoadLocaleFile (&title);
fWindow = win;
SetTitle("Find");
fWindow = win;
this->SetTitle (title.getString ("Find"));
AddShortcut ((ulong)'W', (ulong)B_COMMAND_KEY, new BMessage (MSG_FIND_HIDE));
AddShortcut ((ulong)'Q', (ulong)B_COMMAND_KEY, new BMessage (FPANEL_HIDE));
AddShortcut ((ulong)'W', (ulong)B_COMMAND_KEY, new BMessage (FPANEL_HIDE));
//Build up view
fFindView = new BView(Bounds(), "FindView", B_FOLLOW_ALL, B_WILL_DRAW);
fFindView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
AddChild(fFindView);
BRect r (10, 10, 120, 20);
BTextControl *text_ctl = new BTextControl (r, "text", NULL, NULL, NULL);
AddChild (text_ctl);
font_height height;
fFindView->GetFontHeight(&height);
float lineHeight = height.ascent + height.descent + height.leading;
r.Set (100, 40, 130, 60);
BButton *button = new BButton (r, NULL, "Find", new BMessage (MSG_FIND_START));
AddChild (button);
//These labels are from the bottom up
float buttonsTop = frame.Height() - 19 - lineHeight;
float matchwordBottom = buttonsTop - 4;
float matchwordTop = matchwordBottom - lineHeight - 8;
float matchcaseBottom = matchwordTop - 4;
float matchcaseTop = matchcaseBottom - lineHeight - 8;
float forwardsearchBottom = matchcaseTop - 4;
float forwardsearchTop = forwardsearchBottom - lineHeight - 8;
//These things are calculated from the top
float textRadioTop = 12;
float textRadioBottom = textRadioTop + 2 + lineHeight + 2 + 1;
float textRadioRight = fFindView->StringWidth("Use Text: ") + 30;
float selectionRadioTop = textRadioBottom + 4;
float selectionRadioBottom = selectionRadioTop + lineHeight + 8;
//Divider
float dividerHeight = (selectionRadioBottom + forwardsearchTop) / 2;
//Button Coordinates
float searchbuttonLeft = (frame.Width() - fFindView->StringWidth("Find") - 60) / 2;
float searchbuttonRight = searchbuttonLeft + fFindView->StringWidth("Find") + 60;
//Build the Views
fTextRadio = new BRadioButton(BRect(14, textRadioTop, textRadioRight, textRadioBottom),
"fTextRadio", "Use Text: ", NULL);
fFindView->AddChild(fTextRadio);
fTextRadio->SetValue(1); //enable first option
fFindLabel = new BTextControl(BRect(textRadioRight + 4, textRadioTop, frame.Width() - 14, textRadioBottom),
"fFindLabel", "", "", NULL);
fFindLabel->SetDivider(0);
fFindView->AddChild(fFindLabel);
fFindLabel->MakeFocus(true);
fSelectionRadio = new BRadioButton(BRect(14, selectionRadioTop, frame.Width() - 14, selectionRadioBottom),
"fSelectionRadio", "Use Selection", NULL);
fFindView->AddChild(fSelectionRadio);
fSeparator = new BBox(BRect(6, dividerHeight, frame.Width() - 6, dividerHeight + 1));
fFindView->AddChild(fSeparator);
fForwardSearchBox = new BCheckBox(BRect(14, forwardsearchTop, frame.Width() - 14, forwardsearchBottom),
"fForwardSearchBox", "Search Forward", NULL);
fFindView->AddChild(fForwardSearchBox);
fMatchCaseBox = new BCheckBox(BRect(14, matchcaseTop, frame.Width() - 14, matchcaseBottom),
"fMatchCaseBox", "Match Case", NULL);
fFindView->AddChild(fMatchCaseBox);
fMatchWordBox = new BCheckBox(BRect(14, matchwordTop, frame.Width() - 14, matchwordBottom),
"fMatchWordBox", "Match Word", NULL);
fFindView->AddChild(fMatchWordBox);
fFindButton = new BButton(BRect(searchbuttonLeft, buttonsTop, searchbuttonRight, frame.Height() - 14),
"fFindButton", "Find", new BMessage(MSG_FIND));
fFindButton->MakeDefault(true);
fFindView->AddChild(fFindButton);
Show();
}
FindDlg::~FindDlg (void)
@@ -80,8 +140,47 @@ FindDlg::~FindDlg (void)
}
void
FindDlg::Quit (void)
FindDlg::MessageReceived (BMessage *msg)
{
BWindow::Quit ();
switch (msg->what) {
case B_QUIT_REQUESTED:
Quit();
break;
case MSG_FIND:
SendFindMessage();
break;
case MSG_FIND_HIDE:
Quit();
break;
default:
BWindow::MessageReceived(msg);
break;
}
}
void
FindDlg::Quit (void)
{
fWindow->PostMessage(MSG_FIND_CLOSED);
BWindow::Quit ();
}
void
FindDlg::SendFindMessage (void)
{
BMessage message(MSG_FIND);
if (fTextRadio->Value() == B_CONTROL_ON) {
message.AddString("findstring", fFindLabel->Text());
message.AddBool("findselection", false);
} else
message.AddBool("findselection", true);
//Add the other parameters
message.AddBool("usetext", fTextRadio->Value() == B_CONTROL_ON);
message.AddBool("forwardsearch", fForwardSearchBox->Value() == B_CONTROL_ON);
message.AddBool("matchcase", fMatchCaseBox->Value() == B_CONTROL_ON);
message.AddBool("matchword", fMatchWordBox->Value() == B_CONTROL_ON);
fWindow->PostMessage(&message);
}
+23 -10
View File
@@ -33,29 +33,42 @@
#include <Window.h>
#include <TextView.h>
#include "CurPos.h"
const ulong MSG_FIND = 'msgf';
const ulong MSG_FIND_START = 'msac';
const ulong MSG_FIND_CLOSED = 'mfcl';
class BRect;
class BBitmap;
class BMessage;
class TermWindow;
class BTextControl;
class BRadioButton;
class BCheckBox;
class FindDlg : public BWindow
{
public:
FindDlg(BRect frame, TermWindow *win);
~FindDlg ();
FindDlg (BRect frame, TermWindow *win);
~FindDlg ();
void Find (CurPos *start, CurPos *end);
private:
virtual void Quit (void);
void MessageReceived (BMessage *msg);
private:
virtual void Quit (void);
BString *fFindString;
TermWindow *fWindow;
void SendFindMessage (void);
BView *fFindView;
BTextControl *fFindLabel;
BRadioButton *fTextRadio;
BRadioButton *fSelectionRadio;
BBox *fSeparator;
BCheckBox *fForwardSearchBox;
BCheckBox *fMatchCaseBox;
BCheckBox *fMatchWordBox;
BButton *fFindButton;
BString *fFindString;
TermWindow *fWindow;
};
+3
View File
@@ -3,10 +3,13 @@ SubDir HAIKU_TOP src apps terminal ;
SetSubDirSupportedPlatformsBeOSCompatible ;
AddSubDirSupportedPlatforms libbe_test ;
UseHeaders [ FDirName $(HAIKU_TOP) src kits tracker ] ;
Application Terminal :
AppearPrefView.cpp
CodeConv.cpp
CurPos.cpp
FindDlg.cpp
MenuUtil.cpp
Terminal.cpp
PrefDlg.cpp
+14
View File
@@ -103,6 +103,9 @@ TermBuffer::TermBuffer(int rows, int cols)
mRowSize = rows;
mRowOffset = 0;
mSelStart.Set(-1,-1);
mSelEnd.Set(-1,-1);
buffer_size = gTermPref->getInt32(PREF_HISTORY_SIZE);
if (buffer_size < 1000)
@@ -544,3 +547,14 @@ TermBuffer::GetStringFromRegion(BString &str)
}
}
//Returns the complete internal buffer as a BString
void
TermBuffer::ToString(BString &str)
{
for (int y = 0; y < mRowSize; y++) {
for (int x = 0; x < mNowColSize; x++) {
GetCharFromRegion(x, y, str);
}
}
AvoidWaste(str);
}
+12 -1
View File
@@ -95,15 +95,26 @@ public:
//
void ClearAll (void);
// Set / Unset Selection
//
// Selection Methods
//
void Select (const CurPos &start, const CurPos &end);
void DeSelect (void);
const CurPos &GetSelectionStart (void) { return mSelStart; };
const CurPos &GetSelectionEnd (void) { return mSelEnd; };
int CheckSelectedRegion (const CurPos &pos);
//
// Other methods
//
bool FindWord (const CurPos &pos, CurPos *start, CurPos *end);
void GetCharFromRegion (int x, int y, BString &str);
void AvoidWaste (BString &str);
void ToString (BString &str);
int32 GetArraySize (void);
+2 -1
View File
@@ -63,7 +63,8 @@ const uint32 MENU_ENCODING = 'Menc';
const uint32 MENU_PAGE_SETUP = 'Mpst';
const uint32 MENU_PRINT = 'Mpnt';
const uint32 MENU_FIND_STRING = 'Mfnd';
const uint32 MENU_FIND_AGAIN = 'Mfag';
const uint32 MENU_FIND_FORWARD = 'Mffw';
const uint32 MENU_FIND_BACKWARD = 'Mfbw';
const uint32 MENU_SHOW_COLOR = 'Mcol';
const uint32 M_GET_DEVICE_NUM = 'Mgdn';
+94
View File
@@ -22,6 +22,7 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "TermView.h"
#include "TermWindow.h"
@@ -2248,6 +2249,99 @@ TermView::GetFontInfo(int *width, int *height)
*height = fFontHeight;
}
// Find a string, and select it if found
bool
TermView::Find (const BString &str, bool forwardSearch, bool matchCase, bool matchWord)
{
BString buffer;
CurPos selectionstart, selectionend;
int offset = 0;
int initialresult = -1;
int result = B_ERROR;
//Get the buffer contents
fTextBuffer->ToString(buffer);
selectionstart = fTextBuffer->GetSelectionStart();
selectionend = fTextBuffer->GetSelectionEnd();
if (selectionstart.x >= 0 || selectionstart.y >= 0) {
if (forwardSearch)
//Set the offset to the end of the selection
offset = (selectionend.y) * fTermColumns + selectionend.x;
else
offset = (selectionstart.y) * fTermColumns + selectionstart.x;
}
restart:
//Actual search
if (forwardSearch) {
if (matchCase) {
result = buffer.FindFirst(str, offset);
} else {
result = buffer.IFindFirst(str, offset);
}
} else {
if (matchCase) {
result = buffer.FindLast(str, offset);
} else {
result = buffer.IFindLast(str, offset);
}
}
if (result == B_ERROR) { //Wrap search like Be's Terminal
if (forwardSearch) {
if (matchCase) {
result = buffer.FindFirst(str, 0);
} else {
result = buffer.IFindFirst(str, 0);
}
} else {
if (matchCase) {
result = buffer.FindLast(str, buffer.Length());
} else {
result = buffer.IFindLast(str, buffer.Length());
}
}
}
if (result < 0)
return false;
if (matchWord) {
if (isalnum(buffer.ByteAt(result - 1)) || isalnum(buffer.ByteAt(result + str.Length()))) {
if (initialresult == -1) //Set the initial offset to the first result to aid word matching
initialresult = result;
else if (initialresult == result) //We went round the buffer, nothing found
return false;
if (forwardSearch)
offset = result + str.Length();
else
offset = result;
goto restart;
}
}
//Select the found text
selectionstart.y = result / fTermColumns;
selectionstart.x = result % fTermColumns;
//Length -1 since it seems to count the \0 as well
selectionend.y = (result + str.Length() - 1) / fTermColumns;
selectionend.x = (result + str.Length() - 1) % fTermColumns;
//Update the contents of the view
DeSelect();
Select(selectionstart, selectionend);
return true;
}
//! Get the selected text and copy to str
void
TermView::GetSelection(BString &str)
{
str.SetTo("");
fTextBuffer->GetStringFromRegion(str);
}
// Send DrawRect data to Draw Engine thread.
inline void
TermView::SendDataToDrawEngine(int x1, int y1, int x2, int y2)
+3
View File
@@ -184,6 +184,9 @@ public:
void ScrollScreenDraw (void);
void GetFrameSize (float *width, float *height);
void GetFontInfo (int *, int*);
bool Find (const BString &str, bool forwardSearch, bool matchCase, bool matchWord);
void GetSelection (BString &str);
/*
* PRIVATE MEMBER.
+90 -8
View File
@@ -27,6 +27,7 @@
#include "CodeConv.h"
#include "ColorWindow.h"
#include "MenuUtil.h"
#include "FindDlg.h"
#include "PrefDlg.h"
#include "PrefView.h"
#include "PrefHandler.h"
@@ -173,6 +174,10 @@ TermWindow::InitWindow(void)
fTermParse->InitTermParse(fTermView, fCodeConv);
// Set Coding.
// Init find parameters
fMatchCase = false;
fMatchWord = false;
// Initialize MessageRunner.
fWindowUpdate = new BMessageRunner(BMessenger(this),
@@ -219,13 +224,16 @@ TermWindow::SetupMenu(void)
fEditmenu->AddSeparatorItem ();
fEditmenu->AddItem (new BMenuItem ("Select All", new BMessage (B_SELECT_ALL), 'A'));
fEditmenu->AddItem (new BMenuItem ("Clear All", new BMessage (MENU_CLEAR_ALL), 'L'));
fEditmenu->AddSeparatorItem ();
fEditmenu->AddItem (new BMenuItem ("Find", new BMessage (MENU_FIND_STRING),'F'));
fFindBackwardMenuItem = new BMenuItem ("Find Backward", new BMessage (MENU_FIND_BACKWARD), '[');
fEditmenu->AddItem (fFindBackwardMenuItem);
fFindBackwardMenuItem->SetEnabled(false);
fFindForwardMenuItem = new BMenuItem ("Find Forward", new BMessage (MENU_FIND_FORWARD), ']');
fEditmenu->AddItem (fFindForwardMenuItem);
fFindForwardMenuItem->SetEnabled(false);
/*
// TODO: Implement Finding
fEditmenu->AddSeparatorItem ();
fEditmenu->AddItem (new BMenuItem ("Find", new BMessage (MENU_FIND_STRING),'F'));
fEditmenu->AddItem (new BMenuItem ("Find Again", new BMessage (MENU_FIND_AGAIN), ']'));
*/
fMenubar->AddItem (fEditmenu);
// Make Help Menu.
@@ -277,6 +285,7 @@ TermWindow::MessageReceived(BMessage *message)
BRect r;
BFont halfFont;
BFont fullFont;
bool findselection, forwardsearch, findresult;
switch (message->what) {
case MENU_SWITCH_TERM: {
@@ -303,6 +312,77 @@ TermWindow::MessageReceived(BMessage *message)
fPrefWindow = NULL;
break;
}
case MENU_FIND_STRING: {
if (!fFindPanel) {
BRect r = Frame();
r.left += 20;
r.top += 20;
r.right = r.left + 260;
r.bottom = r.top + 190;
fFindPanel = new FindDlg(r, this);
}
else
fFindPanel->Activate();
break;
}
case MSG_FIND: {
fFindPanel->PostMessage(B_QUIT_REQUESTED);
message->FindBool("findselection", &findselection);
if (!findselection)
message->FindString("findstring", &fFindString);
else
fTermView->GetSelection(fFindString);
if (fFindString.Length() == 0) {
BAlert *alert = new BAlert("find failed", "No search string.", "Okay", NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
fFindBackwardMenuItem->SetEnabled(false);
fFindForwardMenuItem->SetEnabled(false);
break;
}
message->FindBool("forwardsearch", &forwardsearch);
message->FindBool("matchcase", &fMatchCase);
message->FindBool("matchword", &fMatchWord);
findresult = fTermView->Find(fFindString, forwardsearch, fMatchCase, fMatchWord);
if (!findresult) {
BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
fFindBackwardMenuItem->SetEnabled(false);
fFindForwardMenuItem->SetEnabled(false);
break;
}
//Enable the menu items Find Forward and Find Backward
fFindBackwardMenuItem->SetEnabled(true);
fFindForwardMenuItem->SetEnabled(true);
break;
}
case MENU_FIND_FORWARD: {
findresult = fTermView->Find(fFindString, true, fMatchCase, fMatchWord);
if (!findresult) {
BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
}
break;
}
case MENU_FIND_BACKWARD: {
findresult = fTermView->Find(fFindString, false, fMatchCase, fMatchWord);
if (!findresult) {
BAlert *alert = new BAlert("find failed", "Not Found.", "Okay", NULL,
NULL, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
alert->Go();
}
break;
}
case MSG_FIND_CLOSED: {
fFindPanel = NULL;
break;
}
case MENU_FILE_QUIT: {
be_app->PostMessage(B_QUIT_REQUESTED);
break;
@@ -522,8 +602,10 @@ TermWindow::Quit(void)
{
delete fTermParse;
delete fCodeConv;
if(fPrefWindow) fPrefWindow->PostMessage (B_QUIT_REQUESTED);
be_app->PostMessage (B_QUIT_REQUESTED, be_app);
if (fPrefWindow) fPrefWindow->PostMessage (B_QUIT_REQUESTED);
if (fFindPanel) fFindPanel->PostMessage(B_QUIT_REQUESTED);
be_app->PostMessage (B_QUIT_REQUESTED, be_app);
BWindow::Quit ();
}
+6
View File
@@ -87,6 +87,12 @@ private:
BMenuItem *item;
BRect fSavedFrame;
window_look fSavedLook;
//Saved search parameters
BString fFindString;
BMenuItem *fFindForwardMenuItem;
BMenuItem *fFindBackwardMenuItem;
bool fMatchCase;
bool fMatchWord;
};
#endif // TERMWIN_H