]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxlwindow.cpp
GetItem() doesn't ignore column number any more
[wxWidgets.git] / user / wxLayout / wxlwindow.cpp
1 /*-*- c++ -*-********************************************************
2 * wxLwindow.h : a scrolled Window for displaying/entering rich text*
3 * *
4 * (C) 1998, 1999 by Karsten Ballüder (Ballueder@usa.net) *
5 * *
6 * $Id$
7 *******************************************************************/
8
9 #ifdef __GNUG__
10 # pragma implementation "wxlwindow.h"
11 #endif
12
13 #include "wx/wxprec.h"
14 #ifdef __BORLANDC__
15 # pragma hdrstop
16 #endif
17
18
19 #include "Mpch.h"
20 #ifdef M_BASEDIR
21 # ifndef USE_PCH
22 # include "Mcommon.h"
23 # include "gui/wxMenuDefs.h"
24 # include "gui/wxMApp.h"
25 # endif // USE_PCH
26 # include "gui/wxlwindow.h"
27 # include "gui/wxlparser.h"
28 #else
29 # ifdef __WXMSW__
30 # include <windows.h>
31 # undef FindWindow
32 # undef GetCharWidth
33 # undef StartDoc
34 # endif
35
36 # include "wxlwindow.h"
37 # include "wxlparser.h"
38 #endif
39
40 #include <wx/clipbrd.h>
41 #include <wx/textctrl.h>
42 #include <wx/dataobj.h>
43
44 #include <ctype.h>
45
46 #ifdef WXLAYOUT_DEBUG
47 # define WXLO_DEBUG(x) wxLogDebug x
48 #else
49 # define WXLO_DEBUG(x)
50 #endif
51
52 /// offsets to put a nice frame around text
53 #define WXLO_XOFFSET 4
54 #define WXLO_YOFFSET 4
55
56 /// offset to the right and bottom for when to redraw scrollbars
57 #define WXLO_ROFFSET 20
58 #define WXLO_BOFFSET 20
59
60 BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow)
61 EVT_PAINT (wxLayoutWindow::OnPaint)
62 EVT_CHAR (wxLayoutWindow::OnChar)
63 EVT_KEY_UP (wxLayoutWindow::OnKeyUp)
64 EVT_LEFT_DOWN(wxLayoutWindow::OnLeftMouseClick)
65 EVT_RIGHT_DOWN(wxLayoutWindow::OnRightMouseClick)
66 EVT_LEFT_DCLICK(wxLayoutWindow::OnMouseDblClick)
67 EVT_MOTION (wxLayoutWindow::OnMouseMove)
68 EVT_MENU_RANGE(WXLOWIN_MENU_FIRST, WXLOWIN_MENU_LAST, wxLayoutWindow::OnMenu)
69 EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus)
70 EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus)
71 END_EVENT_TABLE()
72
73 wxLayoutWindow::wxLayoutWindow(wxWindow *parent)
74 : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
75 wxHSCROLL | wxVSCROLL | wxBORDER)
76
77 {
78 SetStatusBar(NULL); // don't use statusbar
79 m_Editable = false;
80 m_doSendEvents = false;
81 m_ViewStartX = 0; m_ViewStartY = 0;
82 m_DoPopupMenu = true;
83 m_PopupMenu = MakeFormatMenu();
84 m_memDC = new wxMemoryDC;
85 m_bitmap = new wxBitmap(4,4);
86 m_bitmapSize = wxPoint(4,4);
87 m_llist = new wxLayoutList();
88 m_BGbitmap = NULL;
89 m_ScrollToCursor = false;
90 SetWrapMargin(0);
91 wxPoint max = m_llist->GetSize();
92 SetScrollbars(10, 20 /*lineHeight*/, max.x/10+1, max.y/20+1);
93 EnableScrolling(true,true);
94 m_maxx = max.x; m_maxy = max.y;
95 m_Selecting = false;
96 SetCursorVisibility(-1);
97 SetCursor(wxCURSOR_IBEAM);
98 SetDirty();
99 }
100
101 wxLayoutWindow::~wxLayoutWindow()
102 {
103 delete m_memDC; // deletes bitmap automatically (?)
104 delete m_bitmap;
105 delete m_llist;
106 delete m_PopupMenu;
107 SetBackgroundBitmap(NULL);
108 }
109
110 void
111 wxLayoutWindow::Clear(int family,
112 int size,
113 int style,
114 int weight,
115 int underline,
116 wxColour *fg,
117 wxColour *bg)
118 {
119 GetLayoutList()->Clear(family,size,style,weight,underline,fg,bg);
120 SetBackgroundColour(GetLayoutList()->GetDefaults()->GetBGColour());
121 ResizeScrollbars(true);
122 SetDirty();
123 SetModified(false);
124 wxRect r;
125 int w,h;
126 r.x = r.y = 0; GetSize(&w,&h);
127 r.width = w;
128 r.height = h;
129 DoPaint(&r);
130 }
131
132 #ifdef __WXMSW__
133 long
134 wxLayoutWindow::MSWGetDlgCode()
135 {
136 // if we don't return this, we won't get OnChar() events for TABs and ENTER
137 return DLGC_WANTCHARS | DLGC_WANTARROWS | DLGC_WANTMESSAGE;
138 }
139 #endif //MSW
140
141 void
142 wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event)
143 {
144 wxPaintDC dc( this );
145 PrepareDC( dc );
146 SetFocus();
147
148 wxPoint findPos;
149 findPos.x = dc.DeviceToLogicalX(event.GetX());
150 findPos.y = dc.DeviceToLogicalY(event.GetY());
151
152 findPos.x -= WXLO_XOFFSET;
153 findPos.y -= WXLO_YOFFSET;
154
155 if(findPos.x < 0) findPos.x = 0;
156 if(findPos.y < 0) findPos.y = 0;
157
158 m_ClickPosition = wxPoint(event.GetX(), event.GetY());
159
160 wxPoint cursorPos;
161 bool found;
162 wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos,
163 &cursorPos, &found);
164 wxLayoutObject::UserData *u = obj ? obj->GetUserData() : NULL;
165
166 //has the mouse only been moved?
167 if(eventId == WXLOWIN_MENU_MOUSEMOVE)
168 {
169 // found is only true if we are really over an object, not just
170 // behind it
171 if(found && u && ! m_Selecting)
172 {
173 if(!m_HandCursor)
174 SetCursor(wxCURSOR_HAND);
175 m_HandCursor = TRUE;
176 if(m_StatusBar && m_StatusFieldLabel != -1)
177 {
178 const wxString &label = u->GetLabel();
179 if(label.Length())
180 m_StatusBar->SetStatusText(label,
181 m_StatusFieldLabel);
182 }
183 }
184 else
185 {
186 if(m_HandCursor)
187 SetCursor(wxCURSOR_IBEAM);
188 m_HandCursor = FALSE;
189 if(m_StatusBar && m_StatusFieldLabel != -1)
190 m_StatusBar->SetStatusText("", m_StatusFieldLabel);
191 }
192 if(event.LeftIsDown())
193 {
194 if(! m_Selecting)
195 {
196 m_llist->StartSelection();
197 m_Selecting = true;
198 DoPaint(FALSE);
199 }
200 else
201 {
202 m_llist->ContinueSelection(cursorPos);
203 DoPaint(FALSE);
204 }
205 }
206 if(m_Selecting && ! event.LeftIsDown())
207 {
208 m_llist->EndSelection(cursorPos);
209 m_Selecting = false;
210 DoPaint(FALSE);
211 }
212 if(u) u->DecRef();
213 return;
214 }
215
216 // always move cursor to mouse click:
217 if(obj && eventId == WXLOWIN_MENU_LCLICK)
218 {
219 m_llist->MoveCursorTo(cursorPos);
220 if(m_CursorVisibility == -1)
221 m_CursorVisibility = 1;
222 ScrollToCursor();
223 DoPaint(FALSE); // DoPaint suppresses flicker under GTK
224 }
225
226 if(!m_doSendEvents) // nothing to do
227 {
228 if(u) u->DecRef();
229 return;
230 }
231
232 // only do the menu if activated, editable and not on a clickable object
233 if(eventId == WXLOWIN_MENU_RCLICK
234 && IsEditable()
235 && (! obj || u == NULL))
236 {
237 PopupMenu(m_PopupMenu, m_ClickPosition.x, m_ClickPosition.y);
238 if(u) u->DecRef();
239 return;
240 }
241
242 if(u) u->DecRef();
243 // find the object at this position
244 if(obj)
245 {
246 wxCommandEvent commandEvent(wxEVT_COMMAND_MENU_SELECTED, eventId);
247 commandEvent.SetEventObject( this );
248 commandEvent.SetClientData((char *)obj);
249 GetEventHandler()->ProcessEvent(commandEvent);
250 }
251 }
252
253 /*
254 * Some simple keyboard handling.
255 */
256 void
257 wxLayoutWindow::OnChar(wxKeyEvent& event)
258 {
259 int keyCode = event.KeyCode();
260
261 #ifdef WXLAYOUT_DEBUG
262 if(keyCode == WXK_F1)
263 {
264 m_llist->Debug();
265 return;
266 }
267 #endif
268
269 if(! m_Selecting && event.ShiftDown())
270 {
271 switch(keyCode)
272 {
273 case WXK_UP:
274 case WXK_DOWN:
275 case WXK_RIGHT:
276 case WXK_LEFT:
277 case WXK_PRIOR:
278 case WXK_NEXT:
279 case WXK_HOME:
280 case WXK_END:
281 m_Selecting = true;
282 m_llist->StartSelection();
283 break;
284 default:
285 ;
286 }
287 }
288
289 // If needed, make cursor visible:
290 if(m_CursorVisibility == -1)
291 m_CursorVisibility = 1;
292
293 /* These two nested switches work like this:
294 The first one processes all non-editing keycodes, to move the
295 cursor, etc. It's default will process all keycodes causing
296 modifications to the buffer, but only if editing is allowed.
297 */
298 switch(keyCode)
299 {
300 case WXK_RIGHT:
301 m_llist->MoveCursorHorizontally(1);
302 break;
303 case WXK_LEFT:
304 m_llist->MoveCursorHorizontally(-1);
305 break;
306 case WXK_UP:
307 m_llist->MoveCursorVertically(-1);
308 break;
309 case WXK_DOWN:
310 m_llist->MoveCursorVertically(1);
311 break;
312 case WXK_PRIOR:
313 m_llist->MoveCursorVertically(-20);
314 break;
315 case WXK_NEXT:
316 m_llist->MoveCursorVertically(20);
317 break;
318 case WXK_HOME:
319 m_llist->MoveCursorToBeginOfLine();
320 break;
321 case WXK_END:
322 m_llist->MoveCursorToEndOfLine();
323 break;
324 default:
325 if(keyCode == 'c' && event.ControlDown())
326 Copy();
327 if( IsEditable() )
328 {
329 /* First, handle control keys */
330 if(event.ControlDown() && ! event.AltDown())
331 {
332 switch(keyCode)
333 {
334 case WXK_INSERT:
335 Copy();
336 break;
337 case WXK_DELETE :
338 case 'd':
339 m_llist->Delete(1);
340 break;
341 case 'y':
342 m_llist->DeleteLines(1);
343 break;
344 case 'h': // like backspace
345 if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
346 break;
347 case 'u':
348 m_llist->DeleteToBeginOfLine();
349 break;
350 case 'k':
351 m_llist->DeleteToEndOfLine();
352 break;
353 case 'v':
354 Paste();
355 break;
356 case 'c':
357 Copy();
358 break;
359 case 'x':
360 Cut();
361 break;
362 #ifdef WXLAYOUT_DEBUG
363 case WXK_F1:
364 m_llist->SetFont(-1,-1,-1,-1,true); // underlined
365 break;
366 #endif
367 default:
368 ;
369 }
370 }
371 // ALT only:
372 else if( event.AltDown() && ! event.ControlDown() )
373 {
374 switch(keyCode)
375 {
376 case WXK_DELETE:
377 case 'd':
378 m_llist->DeleteWord();
379 break;
380 default:
381 ;
382 }
383 }
384 // no control keys:
385 else if ( ! event.AltDown() && ! event.ControlDown())
386 {
387 switch(keyCode)
388 {
389 case WXK_INSERT:
390 if(event.ShiftDown())
391 Paste();
392 break;
393 case WXK_DELETE :
394 if(event.ShiftDown())
395 Cut();
396 else
397 m_llist->Delete(1);
398 break;
399 case WXK_BACK: // backspace
400 if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
401 break;
402 case WXK_RETURN:
403 if(m_WrapMargin > 0)
404 m_llist->WrapLine(m_WrapMargin);
405 m_llist->LineBreak();
406 break;
407 default:
408 if((!(event.ControlDown() || event.AltDown() || event.MetaDown()))
409 && (keyCode < 256 && keyCode >= 32)
410 )
411 {
412 wxString tmp;
413 tmp += keyCode;
414 if(m_WrapMargin > 0 && isspace(keyCode))
415 m_llist->WrapLine(m_WrapMargin);
416 m_llist->Insert(tmp);
417 }
418 break;
419 }
420 }
421 SetDirty();
422 SetModified();
423 }// if(IsEditable())
424 }// first switch()
425 if(m_Selecting)
426 {
427 if(event.ShiftDown())
428 m_llist->ContinueSelection();
429 else
430 {
431 m_llist->EndSelection();
432 m_Selecting = false;
433 }
434 }
435
436 ScrollToCursor();
437 wxRect r = *m_llist->GetUpdateRect();
438 DoPaint(&r);
439 }
440
441 void
442 wxLayoutWindow::OnKeyUp(wxKeyEvent& event)
443 {
444 if(event.KeyCode() == WXK_SHIFT && m_llist->IsSelecting())
445 {
446 m_llist->EndSelection();
447 m_Selecting = false;
448 }
449 event.Skip();
450 }
451
452
453 void
454 wxLayoutWindow::ScrollToCursor(void)
455 {
456 wxClientDC dc( this );
457 PrepareDC( dc );
458
459 int x0,y0,x1,y1, dx, dy;
460
461 // Calculate where the top of the visible area is:
462 ViewStart(&x0,&y0);
463 GetScrollPixelsPerUnit(&dx, &dy);
464 x0 *= dx; y0 *= dy;
465
466 WXLO_DEBUG(("ScrollToCursor: ViewStart is %d/%d", x0, y0));
467
468 // Get the size of the visible window:
469 GetClientSize(&x1,&y1);
470 wxASSERT(x1 > 0);
471 wxASSERT(y1 > 0);
472 // As we have the values anyway, use them to avoid unnecessary
473 // scrollbar updates.
474 if(x1 > m_maxx) m_maxx = x1;
475 if(y1 > m_maxy) m_maxy = y1;
476 /* Make sure that the scrollbars are at a position so that the
477 cursor is visible if we are editing. */
478 /** Scroll so that cursor is visible! */
479 WXLO_DEBUG(("m_ScrollToCursor = %d", (int) m_ScrollToCursor));
480 wxPoint cc = m_llist->GetCursorScreenPos(*m_memDC);
481 if(cc.x < x0 || cc.y < y0
482 || cc.x >= x0+(9*x1)/10 || cc.y >= y0+(9*y1/10)) // (9*x)/10 == 90%
483 {
484 int nx, ny;
485 nx = cc.x - x1/2; if(nx < 0) nx = 0;
486 ny = cc.y - y1/2; if(ny < 0) ny = 0;
487 Scroll(nx/dx,ny/dy); // new view start
488 x0 = nx; y0 = ny;
489 m_ScrollToCursor = false; // avoid recursion
490 }
491 }
492
493 void
494 wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
495 {
496 wxRect region = GetUpdateRegion().GetBox();
497 InternalPaint(& region);
498 }
499
500 void
501 wxLayoutWindow::DoPaint(const wxRect *updateRect)
502 {
503 #ifdef __WXGTK__
504 InternalPaint(updateRect);
505 #else
506 Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
507 #endif
508 }
509
510 void
511 wxLayoutWindow::InternalPaint(const wxRect *updateRect)
512 {
513 wxPaintDC dc( this );
514 PrepareDC( dc );
515
516 int x0,y0,x1,y1, dx, dy;
517
518 // Calculate where the top of the visible area is:
519 ViewStart(&x0,&y0);
520 GetScrollPixelsPerUnit(&dx, &dy);
521 x0 *= dx; y0 *= dy;
522
523 // Get the size of the visible window:
524 GetClientSize(&x1,&y1);
525 wxASSERT(x1 > 0);
526 wxASSERT(y1 > 0);
527 // As we have the values anyway, use them to avoid unnecessary
528 // scrollbar updates.
529 if(x1 > m_maxx) m_maxx = x1;
530 if(y1 > m_maxy) m_maxy = y1;
531
532
533 if(updateRect)
534 {
535 WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld",
536 updateRect->x, updateRect->y,
537 updateRect->x+updateRect->width,
538 updateRect->y+updateRect->height));
539 }
540 if(IsDirty())
541 {
542 m_llist->Layout(dc);
543 ResizeScrollbars();
544 }
545 /* Check whether the window has grown, if so, we need to reallocate
546 the bitmap to be larger. */
547 if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y)
548 {
549 wxASSERT(m_bitmapSize.x > 0);
550 wxASSERT(m_bitmapSize.y > 0);
551
552 m_memDC->SelectObject(wxNullBitmap);
553 delete m_bitmap;
554 m_bitmapSize = wxPoint(x1,y1);
555 m_bitmap = new wxBitmap(x1,y1);
556 m_memDC->SelectObject(*m_bitmap);
557 }
558
559 m_memDC->SetDeviceOrigin(0,0);
560 m_memDC->SetBrush(wxBrush(m_llist->GetDefaults()->GetBGColour(),wxSOLID));
561 m_memDC->SetPen(wxPen(m_llist->GetDefaults()->GetBGColour(),
562 0,wxTRANSPARENT));
563 m_memDC->SetLogicalFunction(wxCOPY);
564
565 /* Either fill the background with the background bitmap, or clear
566 it. */
567 if(m_BGbitmap)
568 {
569 CoordType
570 y, x,
571 w = m_BGbitmap->GetWidth(),
572 h = m_BGbitmap->GetHeight();
573 for(y = 0; y < y1; y+=h)
574 for(x = 0; x < x1; x+=w)
575 m_memDC->DrawBitmap(*m_BGbitmap, x, y);
576 m_memDC->SetBackgroundMode(wxTRANSPARENT);
577 }
578 else
579 {
580 // clear the background: (must not be done if we use the update rectangle!)
581 m_memDC->SetBackgroundMode(wxSOLID);
582 m_memDC->DrawRectangle(0,0,x1, y1);
583 }
584
585
586 /* This is the important bit: we tell the list to draw itself: */
587 #if WXLO_DEBUG_URECT
588 if(updateRect)
589 {
590 WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld",
591 updateRect->x, updateRect->y,
592 updateRect->x+updateRect->width,
593 updateRect->y+updateRect->height));
594 }
595 #endif
596
597 // Device origins on the memDC are suspect, we translate manually
598 // with the translate parameter of Draw().
599 wxPoint offset(-x0+WXLO_XOFFSET,-y0+WXLO_YOFFSET);
600 m_llist->Draw(*m_memDC,offset, y0, y0+y1);
601
602 // We start calculating a new update rect before drawing the
603 // cursor, so that the cursor coordinates get included in the next
604 // update rectangle (although they are drawn on the memDC, this is
605 // needed to erase it):
606 m_llist->InvalidateUpdateRect();
607 if(m_CursorVisibility == 1)
608 m_llist->DrawCursor(*m_memDC,
609 m_HaveFocus && IsEditable(), // draw a thick
610 // cursor for editable windows with focus
611 offset);
612
613 // Now copy everything to the screen:
614 #if 0
615 // This somehow doesn't work, but even the following bit with the
616 // whole rect at once is still a bit broken I think.
617 wxRegionIterator ri ( GetUpdateRegion() );
618 if(ri)
619 while(ri)
620 {
621 WXLO_DEBUG(("UpdateRegion: %ld,%ld, %ld,%ld",
622 ri.GetX(),ri.GetY(),ri.GetW(),ri.GetH()));
623 dc.Blit(x0+ri.GetX(),y0+ri.GetY(),ri.GetW(),ri.GetH(),
624 m_memDC,ri.GetX(),ri.GetY(),wxCOPY,FALSE);
625 ri++;
626 }
627 else
628 #endif
629 {
630 // FIXME: Trying to copy only the changed parts, but it does not seem
631 // to work:
632 // x0 = updateRect->x; y0 = updateRect->y;
633 // if(updateRect->height < y1)
634 // y1 = updateRect->height;
635 // y1 += WXLO_YOFFSET; //FIXME might not be needed
636 dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE);
637 }
638
639 ResetDirty();
640 m_ScrollToCursor = false;
641 if(m_StatusBar && m_StatusFieldCursor != -1)
642 {
643 wxString label;
644 label.Printf(_("L:%d C:%d"), m_llist->GetCursorPos().x+1, m_llist->GetCursorPos().y+1);
645 m_StatusBar->SetStatusText(label, m_StatusFieldCursor);
646 }
647 }
648
649 // change the range and position of scrollbars
650 void
651 wxLayoutWindow::ResizeScrollbars(bool exact)
652 {
653 wxPoint max = m_llist->GetSize();
654
655 WXLO_DEBUG(("ResizeScrollbars: GetSize: %ld, %ld", (long int)max.x,
656 (long int) max.y));
657 if(max.x > m_maxx || max.y > m_maxy
658 || max.x > m_maxx-WXLO_ROFFSET || max.y > m_maxy-WXLO_BOFFSET
659 || exact)
660 {
661 if(! exact)
662 {
663 // add an extra bit to the sizes to avoid future updates
664 max.x = max.x+WXLO_ROFFSET;
665 max.y = max.y+WXLO_BOFFSET;
666 }
667 ViewStart(&m_ViewStartX, &m_ViewStartY);
668 SetScrollbars(10, 20, max.x/10+1,max.y/20+1,m_ViewStartX,m_ViewStartY,true);
669 m_maxx = max.x; m_maxy = max.y;
670 }
671 }
672
673 void
674 wxLayoutWindow::Paste(void)
675 {
676 // Read some text
677 if (wxTheClipboard->Open())
678 {
679 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT
680 wxLayoutDataObject wxldo;
681 if (wxTheClipboard->IsSupported( wxldo.GetFormat() ))
682 {
683 wxTheClipboard->GetData(&wxldo);
684 {
685 }
686 //FIXME: missing functionality m_llist->Insert(wxldo.GetList());
687 }
688 else
689 #endif
690 {
691 wxTextDataObject data;
692 if (wxTheClipboard->IsSupported( data.GetFormat() ))
693 {
694 wxTheClipboard->GetData(&data);
695 wxString text = data.GetText();
696 wxLayoutImportText( m_llist, text);
697 }
698 }
699 wxTheClipboard->Close();
700 }
701 #if 0
702 /* My attempt to get the primary selection, but it does not
703 work. :-( */
704 if(text.Length() == 0)
705 {
706 wxTextCtrl tmp_tctrl(this,-1);
707 tmp_tctrl.Paste();
708 text += tmp_tctrl.GetValue();
709 }
710 #endif
711 }
712
713 bool
714 wxLayoutWindow::Copy(bool invalidate)
715 {
716 // Calling GetSelection() will automatically do an EndSelection()
717 // on the list, but we need to take a note of it, too:
718 if(m_Selecting)
719 {
720 m_Selecting = false;
721 m_llist->EndSelection();
722 }
723
724 wxLayoutDataObject wldo;
725 wxLayoutList *llist = m_llist->GetSelection(&wldo, invalidate);
726 if(! llist)
727 return FALSE;
728 // Export selection as text:
729 wxString text;
730 wxLayoutExportObject *export;
731 wxLayoutExportStatus status(llist);
732 while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_TEXT)) != NULL)
733 {
734 if(export->type == WXLO_EXPORT_TEXT)
735 text << *(export->content.text);
736 delete export;
737 }
738 delete llist;
739
740 // The exporter always appends a newline, so we chop it off if it
741 // is there:
742 {
743 size_t len = text.Length();
744 if(len > 2 && text[len-2] == '\r') // Windows
745 text = text.Mid(0,len-2);
746 else if(len > 1 && text[len-1] == '\n')
747 text = text.Mid(0,len-1);
748 }
749
750
751 if (wxTheClipboard->Open())
752 {
753 wxTextDataObject *data = new wxTextDataObject( text );
754 bool rc = wxTheClipboard->SetData( data );
755 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT
756 rc |= wxTheClipboard->AddData( &wldo );
757 #endif
758 wxTheClipboard->Close();
759 return rc;
760 }
761 return FALSE;
762 }
763
764 bool
765 wxLayoutWindow::Cut(void)
766 {
767 if(Copy(false)) // do not invalidate selection after copy
768 {
769 m_llist->DeleteSelection();
770 return TRUE;
771 }
772 else
773 return FALSE;
774 }
775 bool
776 wxLayoutWindow::Find(const wxString &needle,
777 wxPoint * fromWhere)
778 {
779 wxPoint found;
780
781 if(fromWhere == NULL)
782 found = m_llist->FindText(needle, m_llist->GetCursorPos());
783 else
784 found = m_llist->FindText(needle, *fromWhere);
785 if(found.x != -1)
786 {
787 if(fromWhere)
788 {
789 *fromWhere = found;
790 fromWhere->x ++;
791 }
792 m_llist->MoveCursorTo(found);
793 ScrollToCursor();
794 return true;
795 }
796 return false;
797 }
798
799 wxMenu *
800 wxLayoutWindow::MakeFormatMenu()
801 {
802 wxMenu *m = new wxMenu(_("Layout Menu"));
803
804 m->Append(WXLOWIN_MENU_LARGER ,_("&Larger"),_("Switch to larger font."), false);
805 m->Append(WXLOWIN_MENU_SMALLER ,_("&Smaller"),_("Switch to smaller font."), false);
806 m->AppendSeparator();
807 m->Append(WXLOWIN_MENU_UNDERLINE_ON, _("&Underline on"),_("Activate underline mode."), false);
808 m->Append(WXLOWIN_MENU_UNDERLINE_OFF,_("&Underline off"),_("Deactivate underline mode."), false);
809 m->Append(WXLOWIN_MENU_BOLD_ON ,_("&Bold on"),_("Activate bold mode."), false);
810 m->Append(WXLOWIN_MENU_BOLD_OFF ,_("&Bold off"),_("Deactivate bold mode."), false);
811 m->Append(WXLOWIN_MENU_ITALICS_ON ,_("&Italics on"),_("Activate italics mode."), false);
812 m->Append(WXLOWIN_MENU_ITALICS_OFF ,_("&Italics off"),_("Deactivate italics mode."), false);
813 m->AppendSeparator();
814 m->Append(WXLOWIN_MENU_ROMAN ,_("&Roman"),_("Switch to roman font."), false);
815 m->Append(WXLOWIN_MENU_TYPEWRITER,_("&Typewriter"),_("Switch to typewriter font."), false);
816 m->Append(WXLOWIN_MENU_SANSSERIF ,_("&Sans Serif"),_("Switch to sans serif font."), false);
817 return m;
818 }
819
820 void wxLayoutWindow::OnMenu(wxCommandEvent& event)
821 {
822 switch (event.GetId())
823 {
824 case WXLOWIN_MENU_LARGER:
825 m_llist->SetFontLarger(); break;
826 case WXLOWIN_MENU_SMALLER:
827 m_llist->SetFontSmaller(); break;
828 case WXLOWIN_MENU_UNDERLINE_ON:
829 m_llist->SetFontUnderline(true); break;
830 case WXLOWIN_MENU_UNDERLINE_OFF:
831 m_llist->SetFontUnderline(false); break;
832 case WXLOWIN_MENU_BOLD_ON:
833 m_llist->SetFontWeight(wxBOLD); break;
834 case WXLOWIN_MENU_BOLD_OFF:
835 m_llist->SetFontWeight(wxNORMAL); break;
836 case WXLOWIN_MENU_ITALICS_ON:
837 m_llist->SetFontStyle(wxITALIC); break;
838 case WXLOWIN_MENU_ITALICS_OFF:
839 m_llist->SetFontStyle(wxNORMAL); break;
840 case WXLOWIN_MENU_ROMAN:
841 m_llist->SetFontFamily(wxROMAN); break;
842 case WXLOWIN_MENU_TYPEWRITER:
843 m_llist->SetFontFamily(wxFIXED); break;
844 case WXLOWIN_MENU_SANSSERIF:
845 m_llist->SetFontFamily(wxSWISS); break;
846 }
847 }
848
849 void
850 wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
851 {
852 m_HaveFocus = true;
853 //FIXME: need argument DoPaint(); // to repaint the cursor
854 }
855
856 void
857 wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
858 {
859 m_HaveFocus = false;
860 //FIXME: need argument DoPaint(); // to repaint the cursor
861 }