/* * 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 #include #include #include #include #include #include #include #include #include #include #include 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(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); }