haiku/src/apps/stylededit/StyledEditView.cpp

239 lines
5.0 KiB
C++

/*
* Copyright 2002-2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Mattias Sundblad
* Andrew Bachmann
* Axel Dörfler, axeld@pinc-software.de
*/
#include "Constants.h"
#include "StyledEditView.h"
#include <CharacterSet.h>
#include <CharacterSetRoster.h>
#include <DataIO.h>
#include <File.h>
#include <Message.h>
#include <Messenger.h>
#include <Node.h>
#include <Rect.h>
#include <TranslationUtils.h>
#include <UTF8.h>
#include <stdio.h>
#include <stdlib.h>
using namespace BPrivate;
StyledEditView::StyledEditView(BRect viewFrame, BRect textBounds,
BHandler* handler)
:
BTextView(viewFrame, "textview", textBounds, NULL,
&(fInitialColor = ui_color(B_DOCUMENT_TEXT_COLOR)),
B_FOLLOW_ALL, B_FRAME_EVENTS | B_WILL_DRAW)
{
SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR);
SetLowUIColor(ViewUIColor());
fMessenger = new BMessenger(handler);
fSuppressChanges = false;
}
StyledEditView::~StyledEditView()
{
delete fMessenger;
}
void
StyledEditView::FrameResized(float width, float height)
{
BTextView::FrameResized(width, height);
}
void
StyledEditView::DeleteText(int32 start, int32 finish)
{
if (!fSuppressChanges)
fMessenger-> SendMessage(TEXT_CHANGED);
BTextView::DeleteText(start, finish);
_UpdateStatus();
}
void
StyledEditView::InsertText(const char* text, int32 length, int32 offset,
const text_run_array* runs)
{
if (!fSuppressChanges)
fMessenger->SendMessage(TEXT_CHANGED);
BTextView::InsertText(text, length, offset, runs);
_UpdateStatus();
}
void
StyledEditView::Select(int32 start, int32 finish)
{
fMessenger->SendMessage(start == finish ? DISABLE_ITEMS : ENABLE_ITEMS);
BTextView::Select(start, finish);
_UpdateStatus();
}
void
StyledEditView::Reset()
{
fSuppressChanges = true;
SetText("");
fEncoding = "";
fSuppressChanges = false;
}
void
StyledEditView::SetSuppressChanges(bool suppressChanges)
{
fSuppressChanges = suppressChanges;
}
status_t
StyledEditView::GetStyledText(BPositionIO* stream, const char* forceEncoding)
{
if (forceEncoding != NULL)
fEncoding = strcmp(forceEncoding, "auto") != 0 ? forceEncoding : "";
fSuppressChanges = true;
status_t result = BTranslationUtils::GetStyledText(stream, this,
fEncoding.String());
fSuppressChanges = false;
if (result != B_OK)
return result;
BNode* node = dynamic_cast<BNode*>(stream);
if (node != NULL) {
if (forceEncoding == NULL) {
// get encoding
if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) {
// try to read as "int32"
int32 encoding;
ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0,
&encoding, sizeof(encoding));
if (bytesRead == (ssize_t)sizeof(encoding)) {
if (encoding == 65535) {
fEncoding = "UTF-8";
} else {
const BCharacterSet* characterSet
= BCharacterSetRoster::GetCharacterSetByConversionID(encoding);
if (characterSet != NULL)
fEncoding = characterSet->GetName();
}
}
}
}
// TODO: move those into BTranslationUtils::GetStyledText() as well?
// restore alignment
int32 align;
ssize_t bytesRead = node->ReadAttr("alignment", 0, 0, &align, sizeof(align));
if (bytesRead == (ssize_t)sizeof(align))
SetAlignment((alignment)align);
// restore wrapping
bool wrap;
bytesRead = node->ReadAttr("wrap", 0, 0, &wrap, sizeof(wrap));
if (bytesRead == (ssize_t)sizeof(wrap)) {
SetWordWrap(wrap);
if (wrap == false) {
BRect textRect;
textRect = Bounds();
textRect.OffsetTo(B_ORIGIN);
textRect.InsetBy(TEXT_INSET, TEXT_INSET);
// the width comes from stylededit R5. TODO: find a better way
textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y));
SetTextRect(textRect);
}
}
}
return result;
}
status_t
StyledEditView::WriteStyledEditFile(BFile* file)
{
return BTranslationUtils::WriteStyledEditFile(this, file,
fEncoding.String());
}
void
StyledEditView::SetEncoding(uint32 encoding)
{
fEncoding = "";
if (encoding == 0)
return;
const BCharacterSet* set
= BCharacterSetRoster::GetCharacterSetByFontID(encoding);
if (set != NULL)
fEncoding = set->GetName();
}
uint32
StyledEditView::GetEncoding() const
{
if (fEncoding == "")
return 0;
const BCharacterSet* set =
BCharacterSetRoster::FindCharacterSetByName(fEncoding.String());
if (set != NULL)
return set->GetFontID();
return 0;
}
void
StyledEditView::_UpdateStatus()
{
int32 selStart, selFinish;
GetSelection(&selStart, &selFinish);
int32 line = CurrentLine();
int32 lineStart = OffsetAt(line);
int32 column = 1;
int32 tabSize = (int32)ceilf(TabWidth() / StringWidth("s"));
for (int i = lineStart; i < selStart; i++) {
unsigned char ch = ByteAt(i);
if ((ch & 0xC0) != 0x80) {
if (ch == '\t')
while (column % tabSize)
column++;
column++;
}
}
BMessage* message = new BMessage(UPDATE_STATUS);
message->AddInt32("line", line + 1);
message->AddInt32("column", column);
message->AddString("encoding", fEncoding.String());
fMessenger->SendMessage(message);
}