00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llfocusmgr.h"
00035 #include "audioengine.h"
00036 #include "llagent.h"
00037 #include "llinventory.h"
00038 #include "llinventorymodel.h"
00039 #include "llinventoryview.h"
00040
00041 #include "llviewertexteditor.h"
00042
00043 #include "llfloaterchat.h"
00044 #include "llfloaterworldmap.h"
00045 #include "llnotify.h"
00046 #include "llpreview.h"
00047 #include "llpreviewtexture.h"
00048 #include "llpreviewnotecard.h"
00049 #include "llpreviewlandmark.h"
00050 #include "llscrollbar.h"
00051 #include "lltooldraganddrop.h"
00052 #include "llviewercontrol.h"
00053 #include "llviewerimagelist.h"
00054 #include "llviewerwindow.h"
00055 #include "llviewerinventory.h"
00056 #include "llvieweruictrlfactory.h"
00057 #include "llnotecard.h"
00058 #include "llmemorystream.h"
00059 #include "llmenugl.h"
00060
00061 extern BOOL gPacificDaylightTime;
00062
00066 class LLEmbeddedNotecardOpener : public LLInventoryCallback
00067 {
00068 LLViewerTextEditor* mTextEditor;
00069
00070 public:
00071 LLEmbeddedNotecardOpener()
00072 : mTextEditor(NULL)
00073 {
00074 }
00075
00076 void setEditor(LLViewerTextEditor* e) {mTextEditor = e;}
00077
00078
00079 void fire(const LLUUID& inv_item)
00080 {
00081 if(!mTextEditor)
00082 {
00083
00084
00085 return;
00086 }
00087
00088 LLInventoryItem* item = gInventory.getItem(inv_item);
00089 if(!item)
00090 {
00091 llwarns << "Item add reported, but not found in inventory!: " << inv_item << llendl;
00092 }
00093 else
00094 {
00095
00096 if(!LLPreview::show(item->getUUID(), true))
00097 {
00098 if(!gSavedSettings.getBOOL("ShowNewInventory"))
00099 {
00100
00101 S32 left, top;
00102 gFloaterView->getNewFloaterPosition(&left, &top);
00103 LLRect rect = gSavedSettings.getRect("NotecardEditorRect");
00104 rect.translate(left - rect.mLeft, top - rect.mTop);
00105 LLPreviewNotecard* preview;
00106 preview = new LLPreviewNotecard("preview notecard",
00107 rect,
00108 LLString("Embedded Note: ") + item->getName(),
00109 item->getUUID(),
00110 LLUUID::null,
00111 item->getAssetUUID(),
00112 true,
00113 (LLViewerInventoryItem*)item);
00114 preview->setSourceID(LLUUID::null);
00115 preview->setFocus(TRUE);
00116
00117
00118 gFloaterView->adjustToFitScreen(preview, FALSE);
00119 }
00120 }
00121 }
00122 }
00123 };
00124
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 class LLEmbeddedItems
00138 {
00139 public:
00140 LLEmbeddedItems(const LLViewerTextEditor* editor);
00141 ~LLEmbeddedItems();
00142 void clear();
00143
00144
00145 bool empty();
00146
00147 void bindEmbeddedChars(const LLFontGL* font);
00148 void unbindEmbeddedChars(const LLFontGL* font);
00149
00150 BOOL insertEmbeddedItem(LLInventoryItem* item, llwchar* value, bool is_new);
00151 BOOL removeEmbeddedItem( llwchar ext_char );
00152
00153 BOOL hasEmbeddedItem(llwchar ext_char);
00154
00155 void getEmbeddedItemList( std::vector<LLPointer<LLInventoryItem> >& items );
00156 void addItems(const std::vector<LLPointer<LLInventoryItem> >& items);
00157
00158 llwchar getEmbeddedCharFromIndex(S32 index);
00159
00160 void removeUnusedChars();
00161 void copyUsedCharsToIndexed();
00162 S32 getIndexFromEmbeddedChar(llwchar wch);
00163
00164 void markSaved();
00165
00166 static LLInventoryItem* getEmbeddedItem(llwchar ext_char);
00167 static BOOL getEmbeddedItemSaved(llwchar ext_char);
00168
00169 struct embedded_info_t
00170 {
00171 LLPointer<LLInventoryItem> mItem;
00172 BOOL mSaved;
00173 };
00174 private:
00175 typedef std::map<llwchar, embedded_info_t > item_map_t;
00176 static item_map_t sEntries;
00177 static std::stack<llwchar> sFreeEntries;
00178
00179 std::set<llwchar> mEmbeddedUsedChars;
00180 std::vector<llwchar> mEmbeddedIndexedChars;
00181 const LLViewerTextEditor* mEditor;
00182 };
00183
00184
00185 LLEmbeddedItems::item_map_t LLEmbeddedItems::sEntries;
00186 std::stack<llwchar> LLEmbeddedItems::sFreeEntries;
00187
00188 LLEmbeddedItems::LLEmbeddedItems(const LLViewerTextEditor* editor)
00189 : mEditor(editor)
00190 {
00191 }
00192
00193 LLEmbeddedItems::~LLEmbeddedItems()
00194 {
00195 clear();
00196 }
00197
00198 void LLEmbeddedItems::clear()
00199 {
00200
00201 for (std::set<llwchar>::iterator iter = mEmbeddedUsedChars.begin();
00202 iter != mEmbeddedUsedChars.end();)
00203 {
00204 std::set<llwchar>::iterator nextiter = iter++;
00205 removeEmbeddedItem(*nextiter);
00206 }
00207 mEmbeddedUsedChars.clear();
00208 mEmbeddedIndexedChars.clear();
00209 }
00210
00211 bool LLEmbeddedItems::empty()
00212 {
00213 removeUnusedChars();
00214 return mEmbeddedUsedChars.empty();
00215 }
00216
00217
00218 BOOL LLEmbeddedItems::insertEmbeddedItem( LLInventoryItem* item, llwchar* ext_char, bool is_new)
00219 {
00220
00221 llwchar wc_emb;
00222 if (!sFreeEntries.empty())
00223 {
00224 wc_emb = sFreeEntries.top();
00225 sFreeEntries.pop();
00226 }
00227 else if (sEntries.empty())
00228 {
00229 wc_emb = FIRST_EMBEDDED_CHAR;
00230 }
00231 else
00232 {
00233 item_map_t::iterator last = sEntries.end();
00234 --last;
00235 wc_emb = last->first;
00236 if (wc_emb >= LAST_EMBEDDED_CHAR)
00237 {
00238 return FALSE;
00239 }
00240 ++wc_emb;
00241 }
00242
00243 sEntries[wc_emb].mItem = item;
00244 sEntries[wc_emb].mSaved = is_new ? FALSE : TRUE;
00245 *ext_char = wc_emb;
00246 mEmbeddedUsedChars.insert(wc_emb);
00247 return TRUE;
00248 }
00249
00250
00251 BOOL LLEmbeddedItems::removeEmbeddedItem( llwchar ext_char )
00252 {
00253 mEmbeddedUsedChars.erase(ext_char);
00254 item_map_t::iterator iter = sEntries.find(ext_char);
00255 if (iter != sEntries.end())
00256 {
00257 sEntries.erase(ext_char);
00258 sFreeEntries.push(ext_char);
00259 return TRUE;
00260 }
00261 return FALSE;
00262 }
00263
00264
00265 LLInventoryItem* LLEmbeddedItems::getEmbeddedItem(llwchar ext_char)
00266 {
00267 if( ext_char >= FIRST_EMBEDDED_CHAR && ext_char <= LAST_EMBEDDED_CHAR )
00268 {
00269 item_map_t::iterator iter = sEntries.find(ext_char);
00270 if (iter != sEntries.end())
00271 {
00272 return iter->second.mItem;
00273 }
00274 }
00275 return NULL;
00276 }
00277
00278
00279 BOOL LLEmbeddedItems::getEmbeddedItemSaved(llwchar ext_char)
00280 {
00281 if( ext_char >= FIRST_EMBEDDED_CHAR && ext_char <= LAST_EMBEDDED_CHAR )
00282 {
00283 item_map_t::iterator iter = sEntries.find(ext_char);
00284 if (iter != sEntries.end())
00285 {
00286 return iter->second.mSaved;
00287 }
00288 }
00289 return FALSE;
00290 }
00291
00292 llwchar LLEmbeddedItems::getEmbeddedCharFromIndex(S32 index)
00293 {
00294 if (index >= (S32)mEmbeddedIndexedChars.size())
00295 {
00296 llwarns << "No item for embedded char " << index << " using LL_UNKNOWN_CHAR" << llendl;
00297 return LL_UNKNOWN_CHAR;
00298 }
00299 return mEmbeddedIndexedChars[index];
00300 }
00301
00302 void LLEmbeddedItems::removeUnusedChars()
00303 {
00304 std::set<llwchar> used = mEmbeddedUsedChars;
00305 const LLWString& wtext = mEditor->getWText();
00306 for (S32 i=0; i<(S32)wtext.size(); i++)
00307 {
00308 llwchar wc = wtext[i];
00309 if( wc >= FIRST_EMBEDDED_CHAR && wc <= LAST_EMBEDDED_CHAR )
00310 {
00311 used.erase(wc);
00312 }
00313 }
00314
00315 for (std::set<llwchar>::iterator iter = used.begin();
00316 iter != used.end(); ++iter)
00317 {
00318 removeEmbeddedItem(*iter);
00319 }
00320 }
00321
00322 void LLEmbeddedItems::copyUsedCharsToIndexed()
00323 {
00324
00325 removeUnusedChars();
00326
00327
00328 mEmbeddedIndexedChars.clear();
00329 for (std::set<llwchar>::iterator iter = mEmbeddedUsedChars.begin();
00330 iter != mEmbeddedUsedChars.end(); ++iter)
00331 {
00332 mEmbeddedIndexedChars.push_back(*iter);
00333 }
00334 }
00335
00336 S32 LLEmbeddedItems::getIndexFromEmbeddedChar(llwchar wch)
00337 {
00338 S32 idx = 0;
00339 for (std::vector<llwchar>::iterator iter = mEmbeddedIndexedChars.begin();
00340 iter != mEmbeddedIndexedChars.end(); ++iter)
00341 {
00342 if (wch == *iter)
00343 break;
00344 ++idx;
00345 }
00346 if (idx < (S32)mEmbeddedIndexedChars.size())
00347 {
00348 return idx;
00349 }
00350 else
00351 {
00352 llwarns << "Embedded char " << wch << " not found, using 0" << llendl;
00353 return 0;
00354 }
00355 }
00356
00357 BOOL LLEmbeddedItems::hasEmbeddedItem(llwchar ext_char)
00358 {
00359 std::set<llwchar>::iterator iter = mEmbeddedUsedChars.find(ext_char);
00360 if (iter != mEmbeddedUsedChars.end())
00361 {
00362 return TRUE;
00363 }
00364 return FALSE;
00365 }
00366
00367 void LLEmbeddedItems::bindEmbeddedChars( const LLFontGL* font )
00368 {
00369 if( sEntries.empty() )
00370 {
00371 return;
00372 }
00373
00374 for (std::set<llwchar>::iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1)
00375 {
00376 llwchar wch = *iter1;
00377 item_map_t::iterator iter2 = sEntries.find(wch);
00378 if (iter2 == sEntries.end())
00379 {
00380 continue;
00381 }
00382 LLInventoryItem* item = iter2->second.mItem;
00383 if (!item)
00384 {
00385 continue;
00386 }
00387 const char* img_name;
00388 switch( item->getType() )
00389 {
00390 case LLAssetType::AT_TEXTURE:
00391 if(item->getInventoryType() == LLInventoryType::IT_SNAPSHOT)
00392 {
00393 img_name = "inv_item_snapshot.tga";
00394 }
00395 else
00396 {
00397 img_name = "inv_item_texture.tga";
00398 }
00399
00400 break;
00401 case LLAssetType::AT_SOUND: img_name = "inv_item_sound.tga"; break;
00402 case LLAssetType::AT_LANDMARK:
00403 if (item->getFlags() & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
00404 {
00405 img_name = "inv_item_landmark_visited.tga";
00406 }
00407 else
00408 {
00409 img_name = "inv_item_landmark.tga";
00410 }
00411 break;
00412 case LLAssetType::AT_CLOTHING: img_name = "inv_item_clothing.tga"; break;
00413 case LLAssetType::AT_OBJECT:
00414 if (item->getFlags() & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS)
00415 {
00416 img_name = "inv_item_object_multi.tga";
00417 }
00418 else
00419 {
00420 img_name = "inv_item_object.tga";
00421 }
00422 break;
00423 case LLAssetType::AT_NOTECARD: img_name = "inv_item_notecard.tga"; break;
00424 case LLAssetType::AT_LSL_TEXT: img_name = "inv_item_script.tga"; break;
00425 case LLAssetType::AT_BODYPART: img_name = "inv_item_bodypart.tga"; break;
00426 case LLAssetType::AT_ANIMATION: img_name = "inv_item_animation.tga";break;
00427 case LLAssetType::AT_GESTURE: img_name = "inv_item_gesture.tga"; break;
00428 default: llassert(0); continue;
00429 }
00430
00431 LLViewerImage* image = gImageList.getImage(LLUUID(gViewerArt.getString(img_name)), MIPMAP_FALSE, TRUE);
00432
00433 ((LLFontGL*)font)->addEmbeddedChar( wch, image, item->getName() );
00434 }
00435 }
00436
00437 void LLEmbeddedItems::unbindEmbeddedChars( const LLFontGL* font )
00438 {
00439 if( sEntries.empty() )
00440 {
00441 return;
00442 }
00443
00444 for (std::set<llwchar>::iterator iter1 = mEmbeddedUsedChars.begin(); iter1 != mEmbeddedUsedChars.end(); ++iter1)
00445 {
00446 ((LLFontGL*)font)->removeEmbeddedChar(*iter1);
00447 }
00448 }
00449
00450 void LLEmbeddedItems::addItems(const std::vector<LLPointer<LLInventoryItem> >& items)
00451 {
00452 for (std::vector<LLPointer<LLInventoryItem> >::const_iterator iter = items.begin();
00453 iter != items.end(); ++iter)
00454 {
00455 LLInventoryItem* item = *iter;
00456 if (item)
00457 {
00458 llwchar wc;
00459 if (!insertEmbeddedItem( item, &wc, false ))
00460 {
00461 break;
00462 }
00463 mEmbeddedIndexedChars.push_back(wc);
00464 }
00465 }
00466 }
00467
00468 void LLEmbeddedItems::getEmbeddedItemList( std::vector<LLPointer<LLInventoryItem> >& items )
00469 {
00470 for (std::set<llwchar>::iterator iter = mEmbeddedUsedChars.begin(); iter != mEmbeddedUsedChars.end(); ++iter)
00471 {
00472 llwchar wc = *iter;
00473 LLPointer<LLInventoryItem> item = getEmbeddedItem(wc);
00474 if (item)
00475 {
00476 items.push_back(item);
00477 }
00478 }
00479 }
00480
00481 void LLEmbeddedItems::markSaved()
00482 {
00483 for (std::set<llwchar>::iterator iter = mEmbeddedUsedChars.begin(); iter != mEmbeddedUsedChars.end(); ++iter)
00484 {
00485 llwchar wc = *iter;
00486 sEntries[wc].mSaved = TRUE;
00487 }
00488 }
00489
00491
00492 class LLTextCmdInsertEmbeddedItem : public LLTextCmd
00493 {
00494 public:
00495 LLTextCmdInsertEmbeddedItem( S32 pos, LLInventoryItem* item )
00496 : LLTextCmd(pos, FALSE),
00497 mExtCharValue(0)
00498 {
00499 mItem = item;
00500 }
00501
00502 virtual BOOL execute( LLTextEditor* editor, S32* delta )
00503 {
00504 LLViewerTextEditor* viewer_editor = (LLViewerTextEditor*)editor;
00505
00506 viewer_editor->mEmbeddedItemList->removeUnusedChars();
00507 if(viewer_editor->mEmbeddedItemList->insertEmbeddedItem( mItem, &mExtCharValue, true ) )
00508 {
00509 LLWString ws;
00510 ws.assign(1, mExtCharValue);
00511 *delta = insert(editor, mPos, ws );
00512 return (*delta != 0);
00513 }
00514 return FALSE;
00515 }
00516
00517 virtual S32 undo( LLTextEditor* editor )
00518 {
00519 remove(editor, mPos, 1);
00520 return mPos;
00521 }
00522
00523 virtual S32 redo( LLTextEditor* editor )
00524 {
00525 LLWString ws;
00526 ws += mExtCharValue;
00527 insert(editor, mPos, ws );
00528 return mPos + 1;
00529 }
00530 virtual BOOL hasExtCharValue( llwchar value )
00531 {
00532 return (value == mExtCharValue);
00533 }
00534
00535 private:
00536 LLPointer<LLInventoryItem> mItem;
00537 llwchar mExtCharValue;
00538 };
00539
00540 struct LLNotecardCopyInfo
00541 {
00542 LLNotecardCopyInfo(LLViewerTextEditor *ed, LLInventoryItem *item)
00543 : mTextEd(ed)
00544 {
00545 mItem = item;
00546 }
00547
00548 LLViewerTextEditor* mTextEd;
00549
00550
00551 LLPointer<LLInventoryItem> mItem;
00552 };
00553
00554
00555
00556
00557
00558
00559
00560 LLViewerTextEditor::LLViewerTextEditor(const LLString& name,
00561 const LLRect& rect,
00562 S32 max_length,
00563 const LLString& default_text,
00564 const LLFontGL* font,
00565 BOOL allow_embedded_items)
00566 : LLTextEditor(name, rect, max_length, default_text, font, allow_embedded_items),
00567 mDragItemSaved(FALSE),
00568 mInventoryCallback(new LLEmbeddedNotecardOpener)
00569 {
00570 mEmbeddedItemList = new LLEmbeddedItems(this);
00571 mInventoryCallback->setEditor(this);
00572
00573
00574
00575
00576 LLMenuGL* menu = gUICtrlFactory->buildMenu("menu_slurl.xml", this);
00577 if (!menu)
00578 {
00579 menu = new LLMenuGL("");
00580 }
00581 menu->setBackgroundColor(gColors.getColor("MenuPopupBgColor"));
00582
00583 mPopupMenuHandle = menu->mViewHandle;
00584 }
00585
00586 LLViewerTextEditor::~LLViewerTextEditor()
00587 {
00588 delete mEmbeddedItemList;
00589
00590
00591
00592
00593 mInventoryCallback->setEditor(NULL);
00594 }
00595
00597
00598 void LLViewerTextEditor::makePristine()
00599 {
00600 mEmbeddedItemList->markSaved();
00601 LLTextEditor::makePristine();
00602 }
00603
00605
00606 BOOL LLViewerTextEditor::handleToolTip(S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen)
00607 {
00608 if (pointInView(x, y) && getVisible())
00609 {
00610 for (child_list_const_iter_t child_iter = getChildList()->begin();
00611 child_iter != getChildList()->end(); ++child_iter)
00612 {
00613 LLView *viewp = *child_iter;
00614 S32 local_x = x - viewp->getRect().mLeft;
00615 S32 local_y = y - viewp->getRect().mBottom;
00616 if( viewp->handleToolTip(local_x, local_y, msg, sticky_rect_screen ) )
00617 {
00618 return TRUE;
00619 }
00620 }
00621
00622 if( mSegments.empty() )
00623 {
00624 return TRUE;
00625 }
00626
00627 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
00628 if( cur_segment )
00629 {
00630 BOOL has_tool_tip = FALSE;
00631 if( cur_segment->getStyle().getIsEmbeddedItem() )
00632 {
00633 LLWString wtip;
00634 has_tool_tip = getEmbeddedItemToolTipAtPos(cur_segment->getStart(), wtip);
00635 msg = wstring_to_utf8str(wtip);
00636 }
00637 else
00638 {
00639 has_tool_tip = cur_segment->getToolTip( msg );
00640 }
00641 if( has_tool_tip )
00642 {
00643
00644
00645 S32 SLOP = 8;
00646 localPointToScreen(
00647 x - SLOP, y - SLOP,
00648 &(sticky_rect_screen->mLeft), &(sticky_rect_screen->mBottom) );
00649 sticky_rect_screen->mRight = sticky_rect_screen->mLeft + 2 * SLOP;
00650 sticky_rect_screen->mTop = sticky_rect_screen->mBottom + 2 * SLOP;
00651 }
00652 }
00653 return TRUE;
00654 }
00655 return FALSE;
00656 }
00657
00658 BOOL LLViewerTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
00659 {
00660 BOOL handled = FALSE;
00661
00662
00663 handled = LLView::childrenHandleMouseDown(x, y, mask) != NULL;
00664
00665
00666 BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax());
00667 if (mOnScrollEndCallback && was_scrolled_to_bottom)
00668 {
00669 mOnScrollEndCallback(mOnScrollEndData);
00670 }
00671
00672 if( !handled && mTakesNonScrollClicks)
00673 {
00674 if (!(mask & MASK_SHIFT))
00675 {
00676 deselect();
00677 }
00678
00679 BOOL start_select = TRUE;
00680 if( mAllowEmbeddedItems )
00681 {
00682 setCursorAtLocalPos( x, y, FALSE );
00683 llwchar wc = 0;
00684 if (mCursorPos < getLength())
00685 {
00686 wc = mWText[mCursorPos];
00687 }
00688 LLInventoryItem* item_at_pos = LLEmbeddedItems::getEmbeddedItem(wc);
00689 if (item_at_pos)
00690 {
00691 mDragItem = item_at_pos;
00692 mDragItemSaved = LLEmbeddedItems::getEmbeddedItemSaved(wc);
00693 gFocusMgr.setMouseCapture( this );
00694 mMouseDownX = x;
00695 mMouseDownY = y;
00696 S32 screen_x;
00697 S32 screen_y;
00698 localPointToScreen(x, y, &screen_x, &screen_y );
00699 gToolDragAndDrop->setDragStart( screen_x, screen_y );
00700
00701 start_select = FALSE;
00702 }
00703 else
00704 {
00705 mDragItem = NULL;
00706 }
00707 }
00708
00709 if( start_select )
00710 {
00711
00712 if (mask & MASK_SHIFT)
00713 {
00714 S32 old_cursor_pos = mCursorPos;
00715 setCursorAtLocalPos( x, y, TRUE );
00716
00717 if (hasSelection())
00718 {
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740 mSelectionEnd = mCursorPos;
00741 }
00742 else
00743 {
00744 mSelectionStart = old_cursor_pos;
00745 mSelectionEnd = mCursorPos;
00746 }
00747
00748 mIsSelecting = TRUE;
00749
00750 }
00751 else
00752 {
00753 setCursorAtLocalPos( x, y, TRUE );
00754 startSelection();
00755 }
00756 gFocusMgr.setMouseCapture( this );
00757 }
00758
00759 handled = TRUE;
00760 }
00761
00762 if (mTakesFocus)
00763 {
00764 setFocus( TRUE );
00765 handled = TRUE;
00766 }
00767
00768
00769 mKeystrokeTimer.reset();
00770
00771 return handled;
00772 }
00773
00774
00775 BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask)
00776 {
00777 BOOL handled = FALSE;
00778
00779 if (!mDragItem)
00780 {
00781
00782 mHoverSegment = NULL;
00783 }
00784 if( getVisible() )
00785 {
00786 if(hasMouseCapture() )
00787 {
00788 if( mIsSelecting )
00789 {
00790 if (x != mLastSelectionX || y != mLastSelectionY)
00791 {
00792 mLastSelectionX = x;
00793 mLastSelectionY = y;
00794 }
00795
00796 if( y > mTextRect.mTop )
00797 {
00798 mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 );
00799 }
00800 else
00801 if( y < mTextRect.mBottom )
00802 {
00803 mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 );
00804 }
00805
00806 setCursorAtLocalPos( x, y, TRUE );
00807 mSelectionEnd = mCursorPos;
00808
00809 updateScrollFromCursor();
00810 getWindow()->setCursor(UI_CURSOR_IBEAM);
00811 }
00812 else if( mDragItem )
00813 {
00814 S32 screen_x;
00815 S32 screen_y;
00816 localPointToScreen(x, y, &screen_x, &screen_y );
00817 if( gToolDragAndDrop->isOverThreshold( screen_x, screen_y ) )
00818 {
00819 gToolDragAndDrop->beginDrag(
00820 LLAssetType::lookupDragAndDropType( mDragItem->getType() ),
00821 mDragItem->getUUID(),
00822 LLToolDragAndDrop::SOURCE_NOTECARD,
00823 mSourceID, mObjectID);
00824
00825 return gToolDragAndDrop->handleHover( x, y, mask );
00826 }
00827 getWindow()->setCursor(UI_CURSOR_HAND);
00828 }
00829
00830 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (active)" << llendl;
00831 handled = TRUE;
00832 }
00833
00834 if( !handled )
00835 {
00836
00837 handled = LLView::childrenHandleHover(x, y, mask) != NULL;
00838 }
00839
00840 if( handled )
00841 {
00842
00843 mKeystrokeTimer.reset();
00844 }
00845
00846
00847 if( !handled && mTakesNonScrollClicks)
00848 {
00849
00850 if( !mSegments.empty() )
00851 {
00852 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
00853 if( cur_segment )
00854 {
00855 if(cur_segment->getStyle().isLink())
00856 {
00857 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over link, inactive)" << llendl;
00858 getWindow()->setCursor(UI_CURSOR_HAND);
00859 handled = TRUE;
00860 }
00861 else
00862 if(cur_segment->getStyle().getIsEmbeddedItem())
00863 {
00864 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (over embedded item, inactive)" << llendl;
00865 getWindow()->setCursor(UI_CURSOR_HAND);
00866
00867 handled = TRUE;
00868 }
00869 mHoverSegment = cur_segment;
00870 }
00871 }
00872
00873 if( !handled )
00874 {
00875 lldebugst(LLERR_USER_INPUT) << "hover handled by " << getName() << " (inactive)" << llendl;
00876 if (!mScrollbar->getVisible() || x < mRect.getWidth() - SCROLLBAR_SIZE)
00877 {
00878 getWindow()->setCursor(UI_CURSOR_IBEAM);
00879 }
00880 else
00881 {
00882 getWindow()->setCursor(UI_CURSOR_ARROW);
00883 }
00884 handled = TRUE;
00885 }
00886 }
00887 }
00888
00889 return handled;
00890 }
00891
00892
00893 BOOL LLViewerTextEditor::handleMouseUp(S32 x, S32 y, MASK mask)
00894 {
00895 BOOL handled = FALSE;
00896
00897
00898 handled = LLView::childrenHandleMouseUp(x, y, mask) != NULL;
00899
00900
00901 BOOL was_scrolled_to_bottom = (mScrollbar->getDocPos() == mScrollbar->getDocPosMax());
00902 if (mOnScrollEndCallback && was_scrolled_to_bottom)
00903 {
00904 mOnScrollEndCallback(mOnScrollEndData);
00905 }
00906
00907 if( !handled && mTakesNonScrollClicks)
00908 {
00909 if( mIsSelecting )
00910 {
00911
00912 if( y > mTextRect.mTop )
00913 {
00914 mScrollbar->setDocPos( mScrollbar->getDocPos() - 1 );
00915 }
00916 else
00917 if( y < mTextRect.mBottom )
00918 {
00919 mScrollbar->setDocPos( mScrollbar->getDocPos() + 1 );
00920 }
00921
00922 setCursorAtLocalPos( x, y, TRUE );
00923 endSelection();
00924
00925 updateScrollFromCursor();
00926 }
00927
00928 if( !hasSelection() )
00929 {
00930 handleMouseUpOverSegment( x, y, mask );
00931 }
00932
00933 handled = TRUE;
00934 }
00935
00936
00937 mKeystrokeTimer.reset();
00938
00939 if( hasMouseCapture() )
00940 {
00941 if (mDragItem)
00942 {
00943
00944 S32 dx = x - mMouseDownX;
00945 S32 dy = y - mMouseDownY;
00946 if (-2 < dx && dx < 2 && -2 < dy && dy < 2)
00947 {
00948 openEmbeddedItem(mDragItem, mDragItemSaved);
00949 }
00950 }
00951 mDragItem = NULL;
00952 gFocusMgr.setMouseCapture( NULL );
00953 handled = TRUE;
00954 }
00955
00956 return handled;
00957 }
00958
00959 BOOL LLViewerTextEditor::handleRightMouseDown(S32 x, S32 y, MASK mask)
00960 {
00961
00962
00963 BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL;
00964
00965 if(! handled)
00966 {
00967 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
00968 if( cur_segment )
00969 {
00970 if(cur_segment->getStyle().isLink())
00971 {
00972 handled = TRUE;
00973 mHTML = cur_segment->getStyle().getLinkHREF();
00974 }
00975 }
00976 }
00977 LLMenuGL* menu = (LLMenuGL*)LLView::getViewByHandle(mPopupMenuHandle);
00978 if(handled && menu && mParseHTML && mHTML.length() > 0)
00979 {
00980 menu->setVisible(TRUE);
00981 menu->arrange();
00982 menu->updateParent(LLMenuGL::sMenuContainer);
00983 LLMenuGL::showPopup(this, menu, x, y);
00984 mHTML = "";
00985 }
00986 else
00987 {
00988 if(menu && menu->getVisible())
00989 {
00990 menu->setVisible(FALSE);
00991 }
00992 }
00993 return handled;
00994 }
00995
00996 BOOL LLViewerTextEditor::handleDoubleClick(S32 x, S32 y, MASK mask)
00997 {
00998 BOOL handled = FALSE;
00999
01000
01001 handled = LLView::childrenHandleDoubleClick(x, y, mask) != NULL;
01002
01003 if( !handled && mTakesNonScrollClicks)
01004 {
01005 if( mAllowEmbeddedItems )
01006 {
01007 LLTextSegment* cur_segment = getSegmentAtLocalPos( x, y );
01008 if( cur_segment && cur_segment->getStyle().getIsEmbeddedItem() )
01009 {
01010 if( openEmbeddedItemAtPos( cur_segment->getStart() ) )
01011 {
01012 deselect();
01013 setFocus( FALSE );
01014 return TRUE;
01015 }
01016 }
01017 }
01018
01019 if (mTakesFocus)
01020 {
01021 setFocus( TRUE );
01022 }
01023
01024 setCursorAtLocalPos( x, y, FALSE );
01025 deselect();
01026
01027 const LLWString &text = getWText();
01028
01029 if( isPartOfWord( text[mCursorPos] ) )
01030 {
01031
01032 while ((mCursorPos > 0) && isPartOfWord(text[mCursorPos-1]))
01033 {
01034 mCursorPos--;
01035 }
01036 startSelection();
01037
01038 while ((mCursorPos < (S32)text.length()) && isPartOfWord( text[mCursorPos] ) )
01039 {
01040 mCursorPos++;
01041 }
01042
01043 mSelectionEnd = mCursorPos;
01044 }
01045 else if ((mCursorPos < (S32)text.length()) && !iswspace( text[mCursorPos]) )
01046 {
01047
01048 startSelection();
01049 mCursorPos++;
01050 mSelectionEnd = mCursorPos;
01051 }
01052
01053
01054
01055 mIsSelecting = FALSE;
01056
01057
01058 mKeystrokeTimer.reset();
01059
01060 handled = TRUE;
01061 }
01062 return handled;
01063 }
01064
01065
01066
01067
01068
01069 BOOL LLViewerTextEditor::handleDragAndDrop(S32 x, S32 y, MASK mask,
01070 BOOL drop, EDragAndDropType cargo_type, void *cargo_data,
01071 EAcceptance *accept,
01072 LLString& tooltip_msg)
01073 {
01074 BOOL handled = FALSE;
01075
01076 if (mTakesNonScrollClicks)
01077 {
01078 if (getEnabled() && !mReadOnly)
01079 {
01080 switch( cargo_type )
01081 {
01082 case DAD_CALLINGCARD:
01083 if(mAcceptCallingCardNames)
01084 {
01085 if (drop)
01086 {
01087 LLInventoryItem *item = (LLInventoryItem *)cargo_data;
01088 LLString name = item->getName();
01089 appendText(name, true, true);
01090 }
01091 *accept = ACCEPT_YES_COPY_SINGLE;
01092 }
01093 else
01094 {
01095 *accept = ACCEPT_NO;
01096 }
01097 break;
01098
01099 case DAD_TEXTURE:
01100 case DAD_SOUND:
01101 case DAD_LANDMARK:
01102 case DAD_SCRIPT:
01103 case DAD_CLOTHING:
01104 case DAD_OBJECT:
01105 case DAD_NOTECARD:
01106 case DAD_BODYPART:
01107 case DAD_ANIMATION:
01108 case DAD_GESTURE:
01109 {
01110 LLInventoryItem *item = (LLInventoryItem *)cargo_data;
01111 if( mAllowEmbeddedItems )
01112 {
01113 U32 mask_next = item->getPermissions().getMaskNextOwner();
01114 if((mask_next & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
01115 {
01116 if( drop )
01117 {
01118 deselect();
01119 S32 old_cursor = mCursorPos;
01120 setCursorAtLocalPos( x, y, TRUE );
01121 S32 insert_pos = mCursorPos;
01122 setCursorPos(old_cursor);
01123 BOOL inserted = insertEmbeddedItem( insert_pos, item );
01124 if( inserted && (old_cursor > mCursorPos) )
01125 {
01126 setCursorPos(mCursorPos + 1);
01127 }
01128
01129 updateLineStartList();
01130 }
01131 *accept = ACCEPT_YES_COPY_MULTI;
01132 }
01133 else
01134 {
01135 *accept = ACCEPT_NO;
01136 if (tooltip_msg.empty())
01137 {
01138 tooltip_msg.assign("Only items with unrestricted\n"
01139 "'next owner' permissions \n"
01140 "can be attached to notecards.");
01141 }
01142 }
01143 }
01144 else
01145 {
01146 *accept = ACCEPT_NO;
01147 }
01148 break;
01149 }
01150
01151 default:
01152 *accept = ACCEPT_NO;
01153 break;
01154 }
01155 }
01156 else
01157 {
01158
01159 *accept = ACCEPT_NO;
01160 }
01161
01162 handled = TRUE;
01163 lldebugst(LLERR_USER_INPUT) << "dragAndDrop handled by LLViewerTextEditor " << getName() << llendl;
01164 }
01165
01166 return handled;
01167 }
01168
01169 void LLViewerTextEditor::setASCIIEmbeddedText(const LLString& instr)
01170 {
01171 LLWString wtext;
01172 const U8* buffer = (U8*)(instr.c_str());
01173 while (*buffer)
01174 {
01175 llwchar wch;
01176 U8 c = *buffer++;
01177 if (c >= 0x80)
01178 {
01179 S32 index = (S32)(c - 0x80);
01180 wch = mEmbeddedItemList->getEmbeddedCharFromIndex(index);
01181 }
01182 else
01183 {
01184 wch = (llwchar)c;
01185 }
01186 wtext.push_back(wch);
01187 }
01188 setWText(wtext);
01189 }
01190
01191 void LLViewerTextEditor::setEmbeddedText(const LLString& instr)
01192 {
01193 LLWString wtext = utf8str_to_wstring(instr);
01194 for (S32 i=0; i<(S32)wtext.size(); i++)
01195 {
01196 llwchar wch = wtext[i];
01197 if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR )
01198 {
01199 S32 index = wch - FIRST_EMBEDDED_CHAR;
01200 wtext[i] = mEmbeddedItemList->getEmbeddedCharFromIndex(index);
01201 }
01202 }
01203 setWText(wtext);
01204 }
01205
01206 LLString LLViewerTextEditor::getEmbeddedText()
01207 {
01208 #if 1
01209
01210 mEmbeddedItemList->copyUsedCharsToIndexed();
01211 LLWString outtextw;
01212 for (S32 i=0; i<(S32)mWText.size(); i++)
01213 {
01214 llwchar wch = mWText[i];
01215 if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR )
01216 {
01217 S32 index = mEmbeddedItemList->getIndexFromEmbeddedChar(wch);
01218 wch = FIRST_EMBEDDED_CHAR + index;
01219 }
01220 outtextw.push_back(wch);
01221 }
01222 LLString outtext = wstring_to_utf8str(outtextw);
01223 return outtext;
01224 #else
01225
01226 mEmbeddedItemList->copyUsedCharsToIndexed();
01227 LLString outtext;
01228 for (S32 i=0; i<(S32)mWText.size(); i++)
01229 {
01230 llwchar wch = mWText[i];
01231 if( wch >= FIRST_EMBEDDED_CHAR && wch <= LAST_EMBEDDED_CHAR )
01232 {
01233 S32 index = mEmbeddedItemList->getIndexFromEmbeddedChar(wch);
01234 wch = 0x80 | index % 128;
01235 }
01236 else if (wch >= 0x80)
01237 {
01238 wch = LL_UNKNOWN_CHAR;
01239 }
01240 outtext.push_back((U8)wch);
01241 }
01242 return outtext;
01243 #endif
01244 }
01245
01246 LLString LLViewerTextEditor::appendTime(bool prepend_newline)
01247 {
01248 U32 utc_time;
01249 utc_time = time_corrected();
01250
01251
01252 struct tm* timep;
01253
01254
01255
01256 timep = utc_to_pacific_time(utc_time, gPacificDaylightTime);
01257
01258 LLString text = llformat("[%d:%02d] ", timep->tm_hour, timep->tm_min);
01259 appendColoredText(text, false, prepend_newline, LLColor4::grey);
01260
01261 return text;
01262 }
01263
01264
01265
01266
01267 llwchar LLViewerTextEditor::pasteEmbeddedItem(llwchar ext_char)
01268 {
01269 if (mEmbeddedItemList->hasEmbeddedItem(ext_char))
01270 {
01271 return ext_char;
01272 }
01273 LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem(ext_char);
01274 if (item)
01275 {
01276
01277 llwchar new_wc;
01278 if (mEmbeddedItemList->insertEmbeddedItem( item, &new_wc, true ))
01279 {
01280 return new_wc;
01281 }
01282 }
01283 return LL_UNKNOWN_CHAR;
01284 }
01285
01286 void LLViewerTextEditor::bindEmbeddedChars(const LLFontGL* font)
01287 {
01288 mEmbeddedItemList->bindEmbeddedChars( font );
01289 }
01290
01291 void LLViewerTextEditor::unbindEmbeddedChars(const LLFontGL* font)
01292 {
01293 mEmbeddedItemList->unbindEmbeddedChars( font );
01294 }
01295
01296 BOOL LLViewerTextEditor::getEmbeddedItemToolTipAtPos(S32 pos, LLWString &msg)
01297 {
01298 if (pos < getLength())
01299 {
01300 LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem(mWText[pos]);
01301 if( item )
01302 {
01303 msg = utf8str_to_wstring(item->getName());
01304 msg += '\n';
01305 msg += utf8str_to_wstring(item->getDescription());
01306 return TRUE;
01307 }
01308 }
01309 return FALSE;
01310 }
01311
01312
01313 BOOL LLViewerTextEditor::openEmbeddedItemAtPos(S32 pos)
01314 {
01315 if( pos < getLength())
01316 {
01317 LLInventoryItem* item = LLEmbeddedItems::getEmbeddedItem( mWText[pos] );
01318 if( item )
01319 {
01320 BOOL saved = LLEmbeddedItems::getEmbeddedItemSaved( mWText[pos] );
01321 return openEmbeddedItem(item, saved);
01322 }
01323 }
01324 return FALSE;
01325 }
01326
01327
01328 BOOL LLViewerTextEditor::openEmbeddedItem(LLInventoryItem* item, BOOL saved)
01329 {
01330 switch( item->getType() )
01331 {
01332 case LLAssetType::AT_TEXTURE:
01333 openEmbeddedTexture( item );
01334 return TRUE;
01335
01336 case LLAssetType::AT_SOUND:
01337 openEmbeddedSound( item );
01338 return TRUE;
01339
01340 case LLAssetType::AT_NOTECARD:
01341 openEmbeddedNotecard( item, saved );
01342 return TRUE;
01343
01344 case LLAssetType::AT_LANDMARK:
01345 openEmbeddedLandmark( item );
01346 return TRUE;
01347
01348 case LLAssetType::AT_LSL_TEXT:
01349 case LLAssetType::AT_CLOTHING:
01350 case LLAssetType::AT_OBJECT:
01351 case LLAssetType::AT_BODYPART:
01352 case LLAssetType::AT_ANIMATION:
01353 case LLAssetType::AT_GESTURE:
01354 showCopyToInvDialog( item );
01355 return TRUE;
01356 default:
01357 return FALSE;
01358 }
01359 }
01360
01361
01362 void LLViewerTextEditor::openEmbeddedTexture( LLInventoryItem* item )
01363 {
01364
01365 if( !LLPreview::show( item->getUUID() ) )
01366 {
01367
01368 if(item)
01369 {
01370 S32 left, top;
01371 gFloaterView->getNewFloaterPosition(&left, &top);
01372 LLRect rect = gSavedSettings.getRect("PreviewTextureRect");
01373 rect.translate( left - rect.mLeft, top - rect.mTop );
01374
01375 LLPreviewTexture* preview = new LLPreviewTexture("preview texture",
01376 rect,
01377 item->getName(),
01378 item->getAssetUUID(),
01379 TRUE);
01380 preview->setAuxItem( item );
01381 preview->setNotecardInfo(mNotecardInventoryID, mObjectID);
01382 }
01383 }
01384 }
01385
01386 void LLViewerTextEditor::openEmbeddedSound( LLInventoryItem* item )
01387 {
01388
01389 LLVector3d lpos_global = gAgent.getPositionGlobal();
01390 const F32 SOUND_GAIN = 1.0f;
01391 if(gAudiop)
01392 {
01393 F32 volume = SOUND_GAIN * gSavedSettings.getF32("AudioLevelSFX");
01394 gAudiop->triggerSound(item->getAssetUUID(), gAgentID, volume, lpos_global);
01395 }
01396 showCopyToInvDialog( item );
01397 }
01398
01399
01400 void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item )
01401 {
01402 open_landmark((LLViewerInventoryItem*)item, " preview landmark", FALSE, item->getUUID(), TRUE);
01403 }
01404
01405 void LLViewerTextEditor::openEmbeddedNotecard( LLInventoryItem* item, BOOL saved )
01406 {
01407 if (saved)
01408 {
01409
01410
01411
01412 copyInventory(item, gInventoryCallbacks.registerCB(mInventoryCallback));
01413 }
01414 else
01415 {
01416 LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
01417 gViewerWindow->alertXml("ConfirmNotecardSave",
01418 LLViewerTextEditor::onNotecardDialog, (void*)info);
01419 }
01420 }
01421
01422
01423 void LLViewerTextEditor::onNotecardDialog( S32 option, void* userdata )
01424 {
01425 LLNotecardCopyInfo *info = (LLNotecardCopyInfo *)userdata;
01426 if( option == 0 )
01427 {
01428
01429 LLPointer<LLInventoryItem>* itemptr = new LLPointer<LLInventoryItem>(info->mItem);
01430 LLPreview::save( info->mTextEd->mNotecardInventoryID, itemptr);
01431 }
01432 }
01433
01434
01435
01436 void LLViewerTextEditor::showCopyToInvDialog( LLInventoryItem* item )
01437 {
01438 LLNotecardCopyInfo *info = new LLNotecardCopyInfo(this, item);
01439 gViewerWindow->alertXml( "ConfirmItemCopy",
01440 LLViewerTextEditor::onCopyToInvDialog, (void*)info);
01441 }
01442
01443
01444 void LLViewerTextEditor::onCopyToInvDialog( S32 option, void* userdata )
01445 {
01446 LLNotecardCopyInfo *info = (LLNotecardCopyInfo *)userdata;
01447 if( 0 == option )
01448 {
01449 info->mTextEd->copyInventory(info->mItem);
01450 }
01451 delete info;
01452 }
01453
01454
01455
01456
01457 S32 LLViewerTextEditor::insertEmbeddedItem( S32 pos, LLInventoryItem* item )
01458 {
01459 return execute( new LLTextCmdInsertEmbeddedItem( pos, item ) );
01460 }
01461
01462 bool LLViewerTextEditor::importStream(std::istream& str)
01463 {
01464 LLNotecard nc(LLNotecard::MAX_SIZE);
01465 bool success = nc.importStream(str);
01466 if (success)
01467 {
01468 mEmbeddedItemList->clear();
01469 const std::vector<LLPointer<LLInventoryItem> >& items = nc.getItems();
01470 mEmbeddedItemList->addItems(items);
01471
01472 if (mAllowEmbeddedItems)
01473 {
01474 if (nc.getVersion() == 1)
01475 setASCIIEmbeddedText( nc.getText() );
01476 else
01477 setEmbeddedText( nc.getText() );
01478 }
01479 else
01480 {
01481 setText( nc.getText() );
01482 }
01483 }
01484 return success;
01485 }
01486
01487 void LLViewerTextEditor::copyInventory(const LLInventoryItem* item, U32 callback_id)
01488 {
01489 copy_inventory_from_notecard(mObjectID,
01490 mNotecardInventoryID,
01491 item, callback_id);
01492 }
01493
01494 bool LLViewerTextEditor::hasEmbeddedInventory()
01495 {
01496 return (!(mEmbeddedItemList->empty()));
01497 }
01498
01500
01501 BOOL LLViewerTextEditor::importBuffer( const LLString& buffer )
01502 {
01503 LLMemoryStream str((U8*)buffer.c_str(), buffer.length());
01504 return importStream(str);
01505 }
01506
01507 BOOL LLViewerTextEditor::exportBuffer( LLString& buffer )
01508 {
01509 LLNotecard nc(LLNotecard::MAX_SIZE);
01510
01511
01512 nc.setText(getEmbeddedText());
01513
01514
01515 std::vector<LLPointer<LLInventoryItem> > embedded_items;
01516 mEmbeddedItemList->getEmbeddedItemList(embedded_items);
01517 nc.setItems(embedded_items);
01518
01519 std::stringstream out_stream;
01520 nc.exportStream(out_stream);
01521
01522 buffer = out_stream.str();
01523
01524 return TRUE;
01525 }
01526
01527 LLView* LLViewerTextEditor::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory)
01528 {
01529 LLString name("text_editor");
01530 node->getAttributeString("name", name);
01531
01532 LLRect rect;
01533 createRect(node, rect, parent, LLRect());
01534
01535 U32 max_text_length = 255;
01536 node->getAttributeU32("max_length", max_text_length);
01537
01538 BOOL allow_embedded_items = FALSE;
01539 node->getAttributeBOOL("embedded_items", allow_embedded_items);
01540
01541 LLFontGL* font = LLView::selectFont(node);
01542
01543
01544 LLString text = node->getTextContents().substr(0, max_text_length - 1);
01545
01546 if (text.size() > max_text_length)
01547 {
01548
01549 text.erase(max_text_length);
01550 }
01551
01552 LLViewerTextEditor* text_editor = new LLViewerTextEditor(name,
01553 rect,
01554 max_text_length,
01555 "",
01556 font,
01557 allow_embedded_items);
01558
01559 BOOL ignore_tabs = text_editor->mTabToNextField;
01560 node->getAttributeBOOL("ignore_tab", ignore_tabs);
01561
01562 text_editor->setTabToNextField(ignore_tabs);
01563
01564
01565 text_editor->setTextEditorParameters(node);
01566
01567 BOOL hide_scrollbar = FALSE;
01568 node->getAttributeBOOL("hide_scrollbar",hide_scrollbar);
01569 text_editor->setHideScrollbarForShortDocs(hide_scrollbar);
01570
01571 BOOL hide_border = !text_editor->mBorder->getVisible();
01572 node->getAttributeBOOL("hide_border", hide_border);
01573 text_editor->setBorderVisible(!hide_border);
01574
01575 BOOL parse_html = text_editor->mParseHTML;
01576 node->getAttributeBOOL("allow_html", parse_html);
01577 text_editor->setParseHTML(parse_html);
01578
01579 text_editor->initFromXML(node, parent);
01580
01581
01582 text_editor->appendStyledText(text, FALSE, FALSE, NULL);
01583
01584 return text_editor;
01585 }