]> git.saurik.com Git - wxWidgets.git/blob - user/wxLayout/wxlwindow.cpp
80d47b9f80f22cdec0c321fc73341c77876b87e0
[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)
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_DELETE :
335 case 'd':
336 m_llist->Delete(1);
337 break;
338 case 'y':
339 m_llist->DeleteLines(1);
340 break;
341 case 'h': // like backspace
342 if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
343 break;
344 case 'u':
345 m_llist->DeleteToBeginOfLine();
346 break;
347 case 'k':
348 m_llist->DeleteToEndOfLine();
349 break;
350 case 'v':
351 Paste();
352 break;
353 #ifdef WXLAYOUT_DEBUG
354 case WXK_F1:
355 m_llist->SetFont(-1,-1,-1,-1,true); // underlined
356 break;
357 #endif
358 default:
359 ;
360 }
361 }
362 // ALT only:
363 else if( event.AltDown() && ! event.ControlDown() )
364 {
365 switch(keyCode)
366 {
367 case WXK_DELETE:
368 case 'd':
369 m_llist->DeleteWord();
370 break;
371 default:
372 ;
373 }
374 }
375 // no control keys:
376 else if ( ! event.AltDown() && ! event.ControlDown())
377 {
378 switch(keyCode)
379 {
380 case WXK_INSERT:
381 if(event.ShiftDown())
382 Paste();
383 break;
384 case WXK_DELETE :
385 m_llist->Delete(1);
386 break;
387 case WXK_BACK: // backspace
388 if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1);
389 break;
390 case WXK_RETURN:
391 if(m_WrapMargin > 0)
392 m_llist->WrapLine(m_WrapMargin);
393 m_llist->LineBreak();
394 break;
395 default:
396 if((!(event.ControlDown() || event.AltDown() || event.MetaDown()))
397 && (keyCode < 256 && keyCode >= 32)
398 )
399 {
400 wxString tmp;
401 tmp += keyCode;
402 if(m_WrapMargin > 0 && isspace(keyCode))
403 m_llist->WrapLine(m_WrapMargin);
404 m_llist->Insert(tmp);
405 }
406 break;
407 }
408 }
409 SetDirty();
410 SetModified();
411 }// if(IsEditable())
412 }// first switch()
413 if(m_Selecting)
414 {
415 if(event.ShiftDown())
416 m_llist->ContinueSelection();
417 else
418 {
419 m_llist->EndSelection();
420 m_Selecting = false;
421 }
422 }
423
424 ScrollToCursor();
425 wxRect r = *m_llist->GetUpdateRect();
426 DoPaint(&r);
427 }
428
429 void
430 wxLayoutWindow::OnKeyUp(wxKeyEvent& event)
431 {
432 if(event.KeyCode() == WXK_SHIFT && m_llist->IsSelecting())
433 {
434 m_llist->EndSelection();
435 m_Selecting = false;
436 }
437 event.Skip();
438 }
439
440
441 void
442 wxLayoutWindow::ScrollToCursor(void)
443 {
444 wxClientDC dc( this );
445 PrepareDC( dc );
446
447 int x0,y0,x1,y1, dx, dy;
448
449 // Calculate where the top of the visible area is:
450 ViewStart(&x0,&y0);
451 GetScrollPixelsPerUnit(&dx, &dy);
452 x0 *= dx; y0 *= dy;
453
454 WXLO_DEBUG(("ScrollToCursor: ViewStart is %d/%d", x0, y0));
455
456 // Get the size of the visible window:
457 GetClientSize(&x1,&y1);
458 wxASSERT(x1 > 0);
459 wxASSERT(y1 > 0);
460 // As we have the values anyway, use them to avoid unnecessary
461 // scrollbar updates.
462 if(x1 > m_maxx) m_maxx = x1;
463 if(y1 > m_maxy) m_maxy = y1;
464 /* Make sure that the scrollbars are at a position so that the
465 cursor is visible if we are editing. */
466 /** Scroll so that cursor is visible! */
467 WXLO_DEBUG(("m_ScrollToCursor = %d", (int) m_ScrollToCursor));
468 wxPoint cc = m_llist->GetCursorScreenPos(*m_memDC);
469 if(cc.x < x0 || cc.y < y0
470 || cc.x >= x0+(9*x1)/10 || cc.y >= y0+(9*y1/10)) // (9*x)/10 == 90%
471 {
472 int nx, ny;
473 nx = cc.x - x1/2; if(nx < 0) nx = 0;
474 ny = cc.y - y1/2; if(ny < 0) ny = 0;
475 Scroll(nx/dx,ny/dy); // new view start
476 x0 = nx; y0 = ny;
477 m_ScrollToCursor = false; // avoid recursion
478 }
479 }
480
481 void
482 wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) // or: OnDraw(wxDC& dc)
483 {
484 wxRect region = GetUpdateRegion().GetBox();
485 InternalPaint(& region);
486 }
487
488 void
489 wxLayoutWindow::DoPaint(const wxRect *updateRect)
490 {
491 #ifdef __WXGTK__
492 InternalPaint(updateRect);
493 #else
494 Refresh(FALSE, updateRect); // Causes bad flicker under wxGTK!!!
495 #endif
496 }
497
498 void
499 wxLayoutWindow::InternalPaint(const wxRect *updateRect)
500 {
501 wxPaintDC dc( this );
502 PrepareDC( dc );
503
504 int x0,y0,x1,y1, dx, dy;
505
506 // Calculate where the top of the visible area is:
507 ViewStart(&x0,&y0);
508 GetScrollPixelsPerUnit(&dx, &dy);
509 x0 *= dx; y0 *= dy;
510
511 // Get the size of the visible window:
512 GetClientSize(&x1,&y1);
513 wxASSERT(x1 > 0);
514 wxASSERT(y1 > 0);
515 // As we have the values anyway, use them to avoid unnecessary
516 // scrollbar updates.
517 if(x1 > m_maxx) m_maxx = x1;
518 if(y1 > m_maxy) m_maxy = y1;
519
520
521 if(updateRect)
522 {
523 WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld",
524 updateRect->x, updateRect->y,
525 updateRect->x+updateRect->width,
526 updateRect->y+updateRect->height));
527 }
528 if(IsDirty())
529 {
530 m_llist->Layout(dc);
531 ResizeScrollbars();
532 }
533 /* Check whether the window has grown, if so, we need to reallocate
534 the bitmap to be larger. */
535 if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y)
536 {
537 wxASSERT(m_bitmapSize.x > 0);
538 wxASSERT(m_bitmapSize.y > 0);
539
540 m_memDC->SelectObject(wxNullBitmap);
541 delete m_bitmap;
542 m_bitmapSize = wxPoint(x1,y1);
543 m_bitmap = new wxBitmap(x1,y1);
544 m_memDC->SelectObject(*m_bitmap);
545 }
546
547 m_memDC->SetDeviceOrigin(0,0);
548 m_memDC->SetBrush(wxBrush(m_llist->GetDefaults()->GetBGColour(),wxSOLID));
549 m_memDC->SetPen(wxPen(m_llist->GetDefaults()->GetBGColour(),
550 0,wxTRANSPARENT));
551 m_memDC->SetLogicalFunction(wxCOPY);
552
553 /* Either fill the background with the background bitmap, or clear
554 it. */
555 if(m_BGbitmap)
556 {
557 CoordType
558 y, x,
559 w = m_BGbitmap->GetWidth(),
560 h = m_BGbitmap->GetHeight();
561 for(y = 0; y < y1; y+=h)
562 for(x = 0; x < x1; x+=w)
563 m_memDC->DrawBitmap(*m_BGbitmap, x, y);
564 m_memDC->SetBackgroundMode(wxTRANSPARENT);
565 }
566 else
567 {
568 // clear the background: (must not be done if we use the update rectangle!)
569 m_memDC->SetBackgroundMode(wxSOLID);
570 m_memDC->DrawRectangle(0,0,x1, y1);
571 }
572
573
574 /* This is the important bit: we tell the list to draw itself: */
575 #if WXLO_DEBUG_URECT
576 if(updateRect)
577 {
578 WXLO_DEBUG(("Update rect: %ld,%ld / %ld,%ld",
579 updateRect->x, updateRect->y,
580 updateRect->x+updateRect->width,
581 updateRect->y+updateRect->height));
582 }
583 #endif
584
585 // Device origins on the memDC are suspect, we translate manually
586 // with the translate parameter of Draw().
587 wxPoint offset(-x0+WXLO_XOFFSET,-y0+WXLO_YOFFSET);
588 m_llist->Draw(*m_memDC,offset, y0, y0+y1);
589
590 // We start calculating a new update rect before drawing the
591 // cursor, so that the cursor coordinates get included in the next
592 // update rectangle (although they are drawn on the memDC, this is
593 // needed to erase it):
594 m_llist->InvalidateUpdateRect();
595 if(m_CursorVisibility == 1)
596 m_llist->DrawCursor(*m_memDC,
597 m_HaveFocus && IsEditable(), // draw a thick
598 // cursor for editable windows with focus
599 offset);
600
601 // Now copy everything to the screen:
602 #if 0
603 // This somehow doesn't work, but even the following bit with the
604 // whole rect at once is still a bit broken I think.
605 wxRegionIterator ri ( GetUpdateRegion() );
606 if(ri)
607 while(ri)
608 {
609 WXLO_DEBUG(("UpdateRegion: %ld,%ld, %ld,%ld",
610 ri.GetX(),ri.GetY(),ri.GetW(),ri.GetH()));
611 dc.Blit(x0+ri.GetX(),y0+ri.GetY(),ri.GetW(),ri.GetH(),
612 m_memDC,ri.GetX(),ri.GetY(),wxCOPY,FALSE);
613 ri++;
614 }
615 else
616 #endif
617 {
618 // FIXME: Trying to copy only the changed parts, but it does not seem
619 // to work:
620 // x0 = updateRect->x; y0 = updateRect->y;
621 // if(updateRect->height < y1)
622 // y1 = updateRect->height;
623 // y1 += WXLO_YOFFSET; //FIXME might not be needed
624 dc.Blit(x0,y0,x1,y1,m_memDC,0,0,wxCOPY,FALSE);
625 }
626
627 ResetDirty();
628 m_ScrollToCursor = false;
629 if(m_StatusBar && m_StatusFieldCursor != -1)
630 {
631 wxString label;
632 label.Printf(_("L:%d C:%d"), m_llist->GetCursorPos().x+1, m_llist->GetCursorPos().y+1);
633 m_StatusBar->SetStatusText(label, m_StatusFieldCursor);
634 }
635 }
636
637 // change the range and position of scrollbars
638 void
639 wxLayoutWindow::ResizeScrollbars(bool exact)
640 {
641 wxPoint max = m_llist->GetSize();
642
643 WXLO_DEBUG(("ResizeScrollbars: GetSize: %ld, %ld", (long int)max.x,
644 (long int) max.y));
645 if(max.x > m_maxx || max.y > m_maxy
646 || max.x > m_maxx-WXLO_ROFFSET || max.y > m_maxy-WXLO_BOFFSET
647 || exact)
648 {
649 if(! exact)
650 {
651 // add an extra bit to the sizes to avoid future updates
652 max.x = max.x+WXLO_ROFFSET;
653 max.y = max.y+WXLO_BOFFSET;
654 }
655 ViewStart(&m_ViewStartX, &m_ViewStartY);
656 SetScrollbars(10, 20, max.x/10+1,max.y/20+1,m_ViewStartX,m_ViewStartY,true);
657 m_maxx = max.x; m_maxy = max.y;
658 }
659 }
660
661 void
662 wxLayoutWindow::Paste(void)
663 {
664 // Read some text
665 if (wxTheClipboard->Open())
666 {
667 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT
668 wxLayoutDataObject wxldo;
669 if (wxTheClipboard->IsSupported( wxldo.GetFormat() ))
670 {
671 wxTheClipboard->GetData(&wxldo);
672 {
673 }
674 //FIXME: missing functionality m_llist->Insert(wxldo.GetList());
675 }
676 else
677 #endif
678 {
679 wxTextDataObject data;
680 if (wxTheClipboard->IsSupported( data.GetFormat() ))
681 {
682 wxTheClipboard->GetData(&data);
683 wxString text = data.GetText();
684 wxLayoutImportText( m_llist, text);
685 }
686 }
687 wxTheClipboard->Close();
688 }
689 #if 0
690 /* My attempt to get the primary selection, but it does not
691 work. :-( */
692 if(text.Length() == 0)
693 {
694 wxTextCtrl tmp_tctrl(this,-1);
695 tmp_tctrl.Paste();
696 text += tmp_tctrl.GetValue();
697 }
698 #endif
699 }
700
701 bool
702 wxLayoutWindow::Copy(bool invalidate)
703 {
704 // Calling GetSelection() will automatically do an EndSelection()
705 // on the list, but we need to take a note of it, too:
706 if(m_Selecting)
707 {
708 m_Selecting = false;
709 m_llist->EndSelection();
710 }
711
712 wxLayoutDataObject wldo;
713 wxLayoutList *llist = m_llist->GetSelection(&wldo, invalidate);
714 if(! llist)
715 return FALSE;
716 // Export selection as text:
717 wxString text;
718 wxLayoutExportObject *export;
719 wxLayoutExportStatus status(llist);
720 while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_TEXT)) != NULL)
721 {
722 if(export->type == WXLO_EXPORT_TEXT)
723 text << *(export->content.text);
724 delete export;
725 }
726 delete llist;
727
728 // The exporter always appends a newline, so we chop it off if it
729 // is there:
730 {
731 size_t len = text.Length();
732 if(len > 2 && text[len-2] == '\r') // Windows
733 text = text.Mid(0,len-2);
734 else if(len > 1 && text[len-1] == '\n')
735 text = text.Mid(0,len-1);
736 }
737
738
739 if (wxTheClipboard->Open())
740 {
741 wxTextDataObject *data = new wxTextDataObject( text );
742 bool rc = wxTheClipboard->SetData( data );
743 #if wxUSE_PRIVATE_CLIPBOARD_FORMAT
744 rc |= wxTheClipboard->AddData( &wldo );
745 #endif
746 wxTheClipboard->Close();
747 return rc;
748 }
749 return FALSE;
750 }
751
752 bool
753 wxLayoutWindow::Cut(void)
754 {
755 if(Copy(false)) // do not invalidate selection after copy
756 {
757 m_llist->DeleteSelection();
758 return TRUE;
759 }
760 else
761 return FALSE;
762 }
763 bool
764 wxLayoutWindow::Find(const wxString &needle,
765 wxPoint * fromWhere)
766 {
767 wxPoint found;
768
769 if(fromWhere == NULL)
770 found = m_llist->FindText(needle, m_llist->GetCursorPos());
771 else
772 found = m_llist->FindText(needle, *fromWhere);
773 if(found.x != -1)
774 {
775 if(fromWhere)
776 {
777 *fromWhere = found;
778 fromWhere->x ++;
779 }
780 m_llist->MoveCursorTo(found);
781 ScrollToCursor();
782 return true;
783 }
784 return false;
785 }
786
787 wxMenu *
788 wxLayoutWindow::MakeFormatMenu()
789 {
790 wxMenu *m = new wxMenu(_("Layout Menu"));
791
792 m->Append(WXLOWIN_MENU_LARGER ,_("&Larger"),_("Switch to larger font."), false);
793 m->Append(WXLOWIN_MENU_SMALLER ,_("&Smaller"),_("Switch to smaller font."), false);
794 m->AppendSeparator();
795 m->Append(WXLOWIN_MENU_UNDERLINE_ON, _("&Underline on"),_("Activate underline mode."), false);
796 m->Append(WXLOWIN_MENU_UNDERLINE_OFF,_("&Underline off"),_("Deactivate underline mode."), false);
797 m->Append(WXLOWIN_MENU_BOLD_ON ,_("&Bold on"),_("Activate bold mode."), false);
798 m->Append(WXLOWIN_MENU_BOLD_OFF ,_("&Bold off"),_("Deactivate bold mode."), false);
799 m->Append(WXLOWIN_MENU_ITALICS_ON ,_("&Italics on"),_("Activate italics mode."), false);
800 m->Append(WXLOWIN_MENU_ITALICS_OFF ,_("&Italics off"),_("Deactivate italics mode."), false);
801 m->AppendSeparator();
802 m->Append(WXLOWIN_MENU_ROMAN ,_("&Roman"),_("Switch to roman font."), false);
803 m->Append(WXLOWIN_MENU_TYPEWRITER,_("&Typewriter"),_("Switch to typewriter font."), false);
804 m->Append(WXLOWIN_MENU_SANSSERIF ,_("&Sans Serif"),_("Switch to sans serif font."), false);
805 return m;
806 }
807
808 void wxLayoutWindow::OnMenu(wxCommandEvent& event)
809 {
810 switch (event.GetId())
811 {
812 case WXLOWIN_MENU_LARGER:
813 m_llist->SetFontLarger(); break;
814 case WXLOWIN_MENU_SMALLER:
815 m_llist->SetFontSmaller(); break;
816 case WXLOWIN_MENU_UNDERLINE_ON:
817 m_llist->SetFontUnderline(true); break;
818 case WXLOWIN_MENU_UNDERLINE_OFF:
819 m_llist->SetFontUnderline(false); break;
820 case WXLOWIN_MENU_BOLD_ON:
821 m_llist->SetFontWeight(wxBOLD); break;
822 case WXLOWIN_MENU_BOLD_OFF:
823 m_llist->SetFontWeight(wxNORMAL); break;
824 case WXLOWIN_MENU_ITALICS_ON:
825 m_llist->SetFontStyle(wxITALIC); break;
826 case WXLOWIN_MENU_ITALICS_OFF:
827 m_llist->SetFontStyle(wxNORMAL); break;
828 case WXLOWIN_MENU_ROMAN:
829 m_llist->SetFontFamily(wxROMAN); break;
830 case WXLOWIN_MENU_TYPEWRITER:
831 m_llist->SetFontFamily(wxFIXED); break;
832 case WXLOWIN_MENU_SANSSERIF:
833 m_llist->SetFontFamily(wxSWISS); break;
834 }
835 }
836
837 void
838 wxLayoutWindow::OnSetFocus(wxFocusEvent &ev)
839 {
840 m_HaveFocus = true;
841 //FIXME: need argument DoPaint(); // to repaint the cursor
842 }
843
844 void
845 wxLayoutWindow::OnKillFocus(wxFocusEvent &ev)
846 {
847 m_HaveFocus = false;
848 //FIXME: need argument DoPaint(); // to repaint the cursor
849 }