1 /* 2 * Copyright 2002-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Mattias Sundblad 7 * Andrew Bachmann 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 12 #include "Constants.h" 13 #include "StyledEditView.h" 14 15 #include <CharacterSet.h> 16 #include <CharacterSetRoster.h> 17 #include <DataIO.h> 18 #include <File.h> 19 #include <Message.h> 20 #include <Messenger.h> 21 #include <Node.h> 22 #include <Rect.h> 23 #include <TranslationUtils.h> 24 #include <UTF8.h> 25 26 #include <stdio.h> 27 #include <stdlib.h> 28 29 30 using namespace BPrivate; 31 32 33 StyledEditView::StyledEditView(BRect viewFrame, BRect textBounds, 34 BHandler* handler) 35 : 36 BTextView(viewFrame, "textview", textBounds, NULL, 37 &(fInitialColor = ui_color(B_DOCUMENT_TEXT_COLOR)), 38 B_FOLLOW_ALL, B_FRAME_EVENTS | B_WILL_DRAW) 39 { 40 SetViewUIColor(B_DOCUMENT_BACKGROUND_COLOR); 41 SetLowUIColor(ViewUIColor()); 42 43 fMessenger = new BMessenger(handler); 44 fSuppressChanges = false; 45 } 46 47 48 StyledEditView::~StyledEditView() 49 { 50 delete fMessenger; 51 } 52 53 54 void 55 StyledEditView::FrameResized(float width, float height) 56 { 57 BTextView::FrameResized(width, height); 58 } 59 60 61 void 62 StyledEditView::DeleteText(int32 start, int32 finish) 63 { 64 if (!fSuppressChanges) 65 fMessenger-> SendMessage(TEXT_CHANGED); 66 67 BTextView::DeleteText(start, finish); 68 _UpdateStatus(); 69 } 70 71 72 void 73 StyledEditView::InsertText(const char* text, int32 length, int32 offset, 74 const text_run_array* runs) 75 { 76 if (!fSuppressChanges) 77 fMessenger->SendMessage(TEXT_CHANGED); 78 79 BTextView::InsertText(text, length, offset, runs); 80 _UpdateStatus(); 81 } 82 83 84 void 85 StyledEditView::Select(int32 start, int32 finish) 86 { 87 fMessenger->SendMessage(start == finish ? DISABLE_ITEMS : ENABLE_ITEMS); 88 BTextView::Select(start, finish); 89 _UpdateStatus(); 90 } 91 92 93 void 94 StyledEditView::Reset() 95 { 96 fSuppressChanges = true; 97 SetText(""); 98 fEncoding = ""; 99 fSuppressChanges = false; 100 } 101 102 103 void 104 StyledEditView::SetSuppressChanges(bool suppressChanges) 105 { 106 fSuppressChanges = suppressChanges; 107 } 108 109 110 status_t 111 StyledEditView::GetStyledText(BPositionIO* stream, const char* forceEncoding) 112 { 113 if (forceEncoding != NULL) 114 fEncoding = strcmp(forceEncoding, "auto") != 0 ? forceEncoding : ""; 115 116 fSuppressChanges = true; 117 status_t result = BTranslationUtils::GetStyledText(stream, this, 118 fEncoding.String()); 119 fSuppressChanges = false; 120 121 if (result != B_OK) 122 return result; 123 124 BNode* node = dynamic_cast<BNode*>(stream); 125 if (node != NULL) { 126 if (forceEncoding == NULL) { 127 // get encoding 128 if (node->ReadAttrString("be:encoding", &fEncoding) != B_OK) { 129 // try to read as "int32" 130 int32 encoding; 131 ssize_t bytesRead = node->ReadAttr("be:encoding", B_INT32_TYPE, 0, 132 &encoding, sizeof(encoding)); 133 if (bytesRead == (ssize_t)sizeof(encoding)) { 134 if (encoding == 65535) { 135 fEncoding = "UTF-8"; 136 } else { 137 const BCharacterSet* characterSet 138 = BCharacterSetRoster::GetCharacterSetByConversionID(encoding); 139 if (characterSet != NULL) 140 fEncoding = characterSet->GetName(); 141 } 142 } 143 } 144 } 145 // TODO: move those into BTranslationUtils::GetStyledText() as well? 146 147 // restore alignment 148 int32 align; 149 ssize_t bytesRead = node->ReadAttr("alignment", 0, 0, &align, sizeof(align)); 150 if (bytesRead == (ssize_t)sizeof(align)) 151 SetAlignment((alignment)align); 152 153 // restore wrapping 154 bool wrap; 155 bytesRead = node->ReadAttr("wrap", 0, 0, &wrap, sizeof(wrap)); 156 if (bytesRead == (ssize_t)sizeof(wrap)) { 157 SetWordWrap(wrap); 158 if (wrap == false) { 159 BRect textRect; 160 textRect = Bounds(); 161 textRect.OffsetTo(B_ORIGIN); 162 textRect.InsetBy(TEXT_INSET, TEXT_INSET); 163 // the width comes from stylededit R5. TODO: find a better way 164 textRect.SetRightBottom(BPoint(1500.0, textRect.RightBottom().y)); 165 SetTextRect(textRect); 166 } 167 } 168 } 169 170 return result; 171 } 172 173 174 status_t 175 StyledEditView::WriteStyledEditFile(BFile* file) 176 { 177 return BTranslationUtils::WriteStyledEditFile(this, file, 178 fEncoding.String()); 179 } 180 181 182 void 183 StyledEditView::SetEncoding(uint32 encoding) 184 { 185 fEncoding = ""; 186 if (encoding == 0) 187 return; 188 189 const BCharacterSet* set 190 = BCharacterSetRoster::GetCharacterSetByFontID(encoding); 191 192 if (set != NULL) 193 fEncoding = set->GetName(); 194 } 195 196 197 uint32 198 StyledEditView::GetEncoding() const 199 { 200 if (fEncoding == "") 201 return 0; 202 203 const BCharacterSet* set = 204 BCharacterSetRoster::FindCharacterSetByName(fEncoding.String()); 205 if (set != NULL) 206 return set->GetFontID(); 207 208 return 0; 209 } 210 211 212 void 213 StyledEditView::_UpdateStatus() 214 { 215 int32 selStart, selFinish; 216 GetSelection(&selStart, &selFinish); 217 218 int32 line = CurrentLine(); 219 int32 lineStart = OffsetAt(line); 220 221 int32 column = 1; 222 int32 tabSize = (int32)ceilf(TabWidth() / StringWidth("s")); 223 for (int i = lineStart; i < selStart; i++) { 224 unsigned char ch = ByteAt(i); 225 if ((ch & 0xC0) != 0x80) { 226 if (ch == '\t') 227 while (column % tabSize) 228 column++; 229 column++; 230 } 231 } 232 233 BMessage* message = new BMessage(UPDATE_STATUS); 234 message->AddInt32("line", line + 1); 235 message->AddInt32("column", column); 236 message->AddString("encoding", fEncoding.String()); 237 fMessenger->SendMessage(message); 238 } 239