From: Karsten Ballüder Date: Sun, 10 Oct 1999 16:52:34 +0000 (+0000) Subject: updated richedit and nettest X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/89be8239db1ae24f501ac68c5bcff3e5ca2efa84 updated richedit and nettest git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@3915 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/configure.in b/configure.in index 0e2fe1cd60..692bb28004 100644 --- a/configure.in +++ b/configure.in @@ -2947,11 +2947,13 @@ AC_OUTPUT([ samples/listctrl/Makefile samples/mdi/Makefile samples/minifram/Makefile - samples/minimal/Makefile + samples/minimal/Makefile + samples/nettest/Makefile samples/newgrid/Makefile samples/notebook/Makefile samples/printing/Makefile - samples/proplist/Makefile + samples/proplist/Makefile + samples/richedit/Makefile samples/sashtest/Makefile samples/scroll/Makefile samples/splitter/Makefile diff --git a/include/wx/dialup.h b/include/wx/dialup.h index 182374aa15..cfd3dd802b 100644 --- a/include/wx/dialup.h +++ b/include/wx/dialup.h @@ -183,6 +183,7 @@ typedef void (wxObject::*wxDialUpEventFunction)(wxDialUpEvent&); #define EVT_DIALUP_CONNECTED(func) { wxEVT_DIALUP_CONNECTED, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxDialUpEventFunction) & func, NULL}, #define EVT_DIALUP_DISCONNECTED(func) { wxEVT_DIALUP_DISCONNECTED, -1, -1, (wxObjectEventFunction) (wxEventFunction) (wxDialUpEventFunction) & func, NULL}, + #endif // wxUSE_DIALUP_MANAGER #endif // _WX_NET_H diff --git a/samples/richedit/Makefile.in b/samples/richedit/Makefile.in new file mode 100644 index 0000000000..0ed004ec22 --- /dev/null +++ b/samples/richedit/Makefile.in @@ -0,0 +1,21 @@ +# +# File: makefile.unx +# Author: Julian Smart +# Created: 1998 +# Updated: +# Copyright: (c) 1998 Julian Smart +# +# "%W% %G%" +# +# Makefile for richedit example (UNIX). + +top_srcdir = @top_srcdir@ +top_builddir = ../.. +program_dir = samples/richedit + +PROGRAM=wxLayout + +OBJECTS=$(PROGRAM).o kbList.o wxllist.o wxlparser.o wxlwindow.o + +include ../../src/makeprog.env + diff --git a/samples/richedit/wxLayout.cpp b/samples/richedit/wxLayout.cpp index f9957ef8f4..e6a5beb0cf 100644 --- a/samples/richedit/wxLayout.cpp +++ b/samples/richedit/wxLayout.cpp @@ -19,6 +19,7 @@ #include "wxLayout.h" #include +#include #include "Micon.xpm" @@ -299,10 +300,12 @@ void MyFrame::OnCommand( wxCommandEvent &event ) m_lwin->Cut(); m_lwin->Refresh(FALSE); break; +#ifdef M_BASEDIR case ID_FIND: m_lwin->Find("void"); m_lwin->Refresh(FALSE); break; +#endif case ID_HTML: { wxLayoutExportObject *export; diff --git a/samples/richedit/wxllist.cpp b/samples/richedit/wxllist.cpp index e4ca6a4197..97e4fc2001 100644 --- a/samples/richedit/wxllist.cpp +++ b/samples/richedit/wxllist.cpp @@ -34,6 +34,7 @@ #include "Mpch.h" #ifdef M_BASEDIR +# include "Mcommon.h" # include "gui/wxllist.h" # include "gui/wxlparser.h" # define SHOW_SELECTIONS 1 @@ -375,7 +376,22 @@ wxLayoutObjectText::Debug(void) wxLayoutObjectIcon::wxLayoutObjectIcon(wxBitmap const &icon) { + if ( !icon.Ok() ) + { + wxFAIL_MSG("invalid icon"); + + m_Icon = NULL; + + return; + } + +#ifdef __WXMSW__ + // FIXME ugly, ugly, ugly - but the only way to avoid slicing + m_Icon = icon.GetHBITMAP() ? new wxBitmap(icon) + : new wxBitmap(wxBitmap((const wxBitmap &)icon)); +#else // !MSW m_Icon = new wxBitmap(icon); +#endif // MSW/!MSW } @@ -634,6 +650,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist) m_LineNumber = 0; RecalculatePosition(llist); + MarkDirty(); if(m_Previous) { m_LineNumber = m_Previous->GetLineNumber() + 1; @@ -644,8 +661,7 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist) if(m_Next) { m_Next->m_Previous = this; - m_Next->MoveLines(+1); - m_Next->RecalculatePositions(1,llist); + m_Next->ReNumber(); } m_StyleInfo = llist->GetDefaultStyleInfo(); @@ -687,28 +703,6 @@ wxLayoutLine::RecalculatePosition(wxLayoutList *llist) return m_Position; } -void -wxLayoutLine::RecalculatePositions(int recurse, wxLayoutList *llist) -{ - //FIXME: is this really needed? We run Layout() anyway. - // Recursing here, drives computation time up exponentially, as - // each line will cause all following lines to be recalculated. - // Yes, or linenumbers go wrong. - - wxASSERT(recurse >= 0); - wxPoint pos = m_Position; - CoordType height = m_Height; - -// WXLO_TRACE("RecalculatePositions()"); - RecalculatePosition(llist); - if(m_Next) - { - if(recurse > 0) - m_Next->RecalculatePositions(--recurse, llist); - else if(pos != m_Position || m_Height != height) - m_Next->RecalculatePositions(0, llist); - } -} wxLayoutObjectList::iterator wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const @@ -823,11 +817,6 @@ wxLayoutLine::Insert(CoordType xpos, wxLayoutObject *obj) MarkDirty(xpos); - // If we insert a command object, we need to recalculate all lines - // to update their styleinfo structure. - if(obj->GetType() == WXLO_TYPE_CMD) - MarkNextDirty(-1); - CoordType offset; wxLOiterator i = FindObject(xpos, &offset); if(i == NULLIT) @@ -923,10 +912,6 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos) len = (**i).GetLength(); m_Length -= len; npos -= len; - // If we delete a command object, we need to recalculate all lines - // to update their styleinfo structure. - if((**i).GetType() == WXLO_TYPE_CMD) - MarkNextDirty(-1); m_ObjectList.erase(i); } else @@ -963,18 +948,6 @@ wxLayoutLine::Delete(CoordType xpos, CoordType npos) return npos; } -void -wxLayoutLine::MarkNextDirty(int recurse) -{ - wxLayoutLine *line = GetNextLine(); - while(line && (recurse == -1 || recurse >= 0)) - { - line->MarkDirty(); - line = line->GetNextLine(); - if(recurse > 0) recurse --; - } -} - bool wxLayoutLine::DeleteWord(CoordType xpos) { @@ -1032,28 +1005,15 @@ wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist) if(m_Previous) m_Previous->m_Next = m_Next; - wxLayoutLine *next = m_Next; - if ( next ) - { - // get the line numbers right again - next->MoveLines(-1); - } - - if(update) - { - if ( next ) - next->RecalculatePositions(1, llist); + // get the line numbers right again + if ( update && m_Next) + m_Next->ReNumber(); - /* We assume that if we have more than one object in the list, - this means that we have a command object, so we need to - update the following lines. */ - if(m_ObjectList.size() > 1 || - ( m_ObjectList.begin() != NULLIT && - (**m_ObjectList.begin()).GetType() == WXLO_TYPE_CMD) - ) - MarkNextDirty(-1); - } + MarkDirty(); + // we can't use m_Next after "delete this", so we must save this pointer + // first + wxLayoutLine *next = m_Next; delete this; llist->DecNumLines(); @@ -1138,6 +1098,8 @@ wxLayoutLine::Layout(wxDC &dc, bool cursorFound = false; + RecalculatePosition(llist); + if(cursorPos) { *cursorPos = m_Position; @@ -1250,10 +1212,9 @@ wxLayoutLine::Layout(wxDC &dc, // tell next line about coordinate change if(m_Next && m_Height != heightOld) { - // FIXME isn't this done in RecalculatePositions() below anyhow? - m_Next->RecalculatePositions(0, llist); + m_Next->MarkDirty(); } - + // We need to check whether we found a valid cursor size: if(cursorPos && cursorSize) { @@ -1269,7 +1230,6 @@ wxLayoutLine::Layout(wxDC &dc, if(m_BaseLine >= cursorSize->y) // the normal case anyway cursorPos->y += m_BaseLine-cursorSize->y; } - RecalculatePositions(1, llist); MarkClean(); } @@ -1281,24 +1241,6 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist) MarkDirty(xpos); - /* If we are at the begin of a line, we want to move all other - lines down and stay with the cursor where we are. However, if we - are in an empty line, we want to move down with it. */ - if(xpos == 0 && GetLength() > 0) - { // insert an empty line before this one - wxLayoutLine *prev = new wxLayoutLine(m_Previous, llist); - if(m_Previous == NULL) - { // We were in first line, need to link in new empty line - // before this. - prev->m_Next = this; - m_Previous = prev; - m_Previous->m_Height = 0; // this is a wild guess - } - if(m_Next) - m_Next->RecalculatePositions(1, llist); - return m_Previous; - } - CoordType offset; wxLOiterator i = FindObject(xpos, &offset); if(i == NULLIT) @@ -1335,10 +1277,20 @@ wxLayoutLine::Break(CoordType xpos, wxLayoutList *llist) m_ObjectList.remove(i); // remove without deleting it } if(m_Next) - m_Next->RecalculatePositions(2, llist); + m_Next->MarkDirty(); return newLine; } +void +wxLayoutLine::ReNumber(void) +{ + CoordType lineNo = m_Previous ? m_Previous->m_LineNumber+1 : 0; + m_LineNumber = lineNo++; + + for(wxLayoutLine *next = GetNextLine(); + next; next = next->GetNextLine()) + next->m_LineNumber = lineNo++; +} void wxLayoutLine::MergeNextLine(wxLayoutList *llist) @@ -1380,7 +1332,7 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist) SetNext(nextLine); if ( nextLine ) { - nextLine->MoveLines(-1); + nextLine->ReNumber(); } else { @@ -1554,12 +1506,15 @@ wxLayoutList::wxLayoutList() m_numLines = 0; m_FirstLine = NULL; + SetAutoFormatting(TRUE); + ForceTotalLayout(TRUE); // for the first time, do all InvalidateUpdateRect(); Clear(); } wxLayoutList::~wxLayoutList() { + SetAutoFormatting(FALSE); InternalClear(); Empty(); m_FirstLine->DeleteLine(false, this); @@ -1753,7 +1708,7 @@ wxLayoutList::MoveCursorVertically(int n) if(! m_CursorLine) { m_CursorLine = last; - m_CursorPos.y ++; + m_CursorPos.y --; rc = false; } else @@ -1992,7 +1947,8 @@ wxLayoutList::Insert(wxString const &text) m_movedCursor = true; - m_CursorLine->RecalculatePositions(0, this); + if(m_AutoFormat) + m_CursorLine->MarkDirty(); return true; } @@ -2011,7 +1967,8 @@ wxLayoutList::Insert(wxLayoutObject *obj) m_CursorPos.x += obj->GetLength(); m_movedCursor = true; - m_CursorLine->RecalculatePositions(0, this); + if(m_AutoFormat) + m_CursorLine->MarkDirty(); return true; } @@ -2094,7 +2051,7 @@ wxLayoutList::WrapLine(CoordType column) Delete(1); // delete the space m_CursorPos.x = newpos; - m_CursorLine->RecalculatePositions(1, this); + m_CursorLine->MarkDirty(); m_movedCursor = true; @@ -2197,7 +2154,8 @@ wxLayoutList::DeleteLines(int n) { // we cannot delete this line, but we can clear it MoveCursorToBeginOfLine(); DeleteToEndOfLine(); - m_CursorLine->RecalculatePositions(2, this); + if(m_AutoFormat) + m_CursorLine->MarkDirty(); return n-1; } //else: @@ -2208,13 +2166,16 @@ wxLayoutList::DeleteLines(int n) wxASSERT(m_FirstLine); wxASSERT(m_CursorLine); } - m_CursorLine->RecalculatePositions(2, this); + if(m_AutoFormat) + m_CursorLine->MarkDirty(); return n; } void wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) { + if(! m_AutoFormat) + return; wxLayoutLine *line = m_FirstLine; // first, make sure everything is calculated - this might not be @@ -2230,7 +2191,7 @@ wxLayoutList::Recalculate(wxDC &dc, CoordType bottom) } wxPoint -wxLayoutList::GetCursorScreenPos(wxDC &dc) +wxLayoutList::GetCursorScreenPos(void) const { return m_CursorScreenPos; } @@ -2247,18 +2208,39 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll, // needed, optimise it later ApplyStyle(m_DefaultStyleInfo, dc); - // This one we always Layout() to get the current cursor - // coordinates on the screen: - m_CursorLine->MarkDirty(); - bool wasDirty = false; + + if(m_ReLayoutAll) + { + forceAll = TRUE; + bottom = -1; + } + ForceTotalLayout(FALSE); + + + // If one line was dirty, we need to re-calculate all + // following lines, too. + bool wasDirty = forceAll; wxLayoutLine *line = m_FirstLine; while(line) { if(! wasDirty) ApplyStyle(line->GetStyleInfo(), dc); - if(forceAll || line->IsDirty() - || (cpos && line->GetLineNumber() == cpos->y)) + if( + // if any previous line was dirty, we need to layout all + // following lines: + wasDirty + // layout dirty lines: + || line->IsDirty() + // always layout the cursor line toupdate the cursor + // position and size: + || line == m_CursorLine + // or if it's the line we are asked to look for: + || (cpos && line->GetLineNumber() == cpos->y) + ) { + if(line->IsDirty()) + wasDirty = true; + // The following Layout() calls will update our // m_CurrentStyleInfo if needed. if(line == m_CursorLine) @@ -2275,7 +2257,7 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll, if ( csize ) *csize = m_CursorSize; } - } + } else if(cpos && line->GetLineNumber() == cpos->y) line->Layout(dc, this, @@ -2286,16 +2268,16 @@ wxLayoutList::Layout(wxDC &dc, CoordType bottom, bool forceAll, // little condition to speed up redrawing: if(bottom != -1 && line->GetPosition().y > bottom) break; - wasDirty = true; } - line->RecalculatePositions(1, this); line = line->GetNextLine(); } +#ifndef WXLAYOUT_USE_CARET // can only be 0 if we are on the first line and have no next line wxASSERT(m_CursorSize.x != 0 || (m_CursorLine && m_CursorLine->GetNextLine() == NULL && m_CursorLine == m_FirstLine)); +#endif // WXLAYOUT_USE_CARET AddCursorPosToUpdateRect(); } @@ -2311,7 +2293,8 @@ void wxLayoutList::Draw(wxDC &dc, wxPoint const &offset, CoordType top, - CoordType bottom) + CoordType bottom, + bool clipStrictly) { wxLayoutLine *line = m_FirstLine; @@ -2332,29 +2315,27 @@ wxLayoutList::Draw(wxDC &dc, m_Selection.m_discarded = false; } - /* We need to re-layout all dirty lines to update styleinfos - etc. However, somehow we don't find all dirty lines... */ - Layout(dc); //,-1,true); //FIXME + /* This call to Layout() will re-calculate and update all lines + marked as dirty. + */ + Layout(dc, bottom); + ApplyStyle(m_DefaultStyleInfo, dc); wxBrush brush(m_CurrentStyleInfo.m_bg, wxSOLID); dc.SetBrush(brush); dc.SetBackgroundMode(wxTRANSPARENT); - bool style_set = false; while(line) { // only draw if between top and bottom: if((top == -1 || line->GetPosition().y + line->GetHeight() > top)) { -// if(! style_set) - { - ApplyStyle(line->GetStyleInfo(), dc); - style_set = true; - } + ApplyStyle(line->GetStyleInfo(), dc); // little condition to speed up redrawing: - if(bottom != -1 - && line->GetPosition().y+line->GetHeight() >= bottom) + if( bottom != -1 + && line->GetPosition().y + +(clipStrictly ? line->GetHeight() : 0) >= bottom) break; line->Draw(dc, this, offset); } @@ -2540,17 +2521,17 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos) wxASSERT(m_Selection.m_valid == false); WXLO_DEBUG(("Continuing selection at %ld/%ld", cpos.x, cpos.y)); - if ( m_Selection.m_CursorB <= cpos ) - { m_Selection.m_ScreenB = spos; - m_Selection.m_CursorB = cpos; - } - else - { - m_Selection.m_ScreenA = spos; - m_Selection.m_CursorA = cpos; - } + m_Selection.m_CursorB = cpos;} +void +wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos) +{ + wxPoint cpos(cposOrig); + if(cpos.x == -1) + cpos = m_CursorPos; + ContinueSelection(cpos); + WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y)); // we always want m_CursorA <= m_CursorB! if( m_Selection.m_CursorA > m_Selection.m_CursorB ) { @@ -2563,18 +2544,12 @@ wxLayoutList::ContinueSelection(const wxPoint& cposOrig, const wxPoint& spos) m_Selection.m_ScreenB = m_Selection.m_ScreenA; m_Selection.m_ScreenA = help; } -} - -void -wxLayoutList::EndSelection(const wxPoint& cposOrig, const wxPoint& spos) -{ - wxPoint cpos(cposOrig); - if(cpos.x == -1) - cpos = m_CursorPos; - ContinueSelection(cpos); - WXLO_DEBUG(("Ending selection at %ld/%ld", cpos.x, cpos.y)); m_Selection.m_selecting = false; m_Selection.m_valid = true; + /// In case we just clicked somewhere, the selection will have zero + /// size, so we discard it immediately. + if(m_Selection.m_CursorA == m_Selection.m_CursorB) + DiscardSelection(); } void @@ -2600,7 +2575,12 @@ wxLayoutList::IsSelected(const wxPoint &cursor) const if ( !HasSelection() ) return false; - return m_Selection.m_CursorA <= cursor && cursor <= m_Selection.m_CursorB; + return ( + (m_Selection.m_CursorA <= cursor + && cursor <= m_Selection.m_CursorB) + || (m_Selection.m_CursorB <= cursor + && cursor <= m_Selection.m_CursorA) + ); } @@ -2620,7 +2600,10 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from, return 0; CoordType y = line->GetLineNumber(); - if(m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y) + if( + (m_Selection.m_CursorA.y < y && m_Selection.m_CursorB.y > y) + || (m_Selection.m_CursorB.y < y && m_Selection.m_CursorA.y > y) + ) return 1; else if(m_Selection.m_CursorA.y == y) { @@ -2628,7 +2611,18 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from, if(m_Selection.m_CursorB.y == y) *to = m_Selection.m_CursorB.x; else - *to = line->GetLength(); + { + if(m_Selection.m_CursorB > m_Selection.m_CursorA) + *to = line->GetLength(); + else + *to = 0; + } + if(*to < *from) + { + CoordType help = *to; + *to = *from; + *from = help; + } return -1; } else if(m_Selection.m_CursorB.y == y) @@ -2637,7 +2631,18 @@ wxLayoutList::IsSelected(const wxLayoutLine *line, CoordType *from, if(m_Selection.m_CursorA.y == y) *from = m_Selection.m_CursorA.x; else - *from = 0; + { + if(m_Selection.m_CursorB > m_Selection.m_CursorA) + *from = 0; + else + *from = line->GetLength(); + } + if(*to < *from) + { + CoordType help = *to; + *to = *from; + *from = help; + } return -1; } else @@ -2665,7 +2670,10 @@ wxLayoutList::DeleteSelection(void) wxLayoutLine * firstLine = GetLine(m_Selection.m_CursorA.y), * lastLine = GetLine(m_Selection.m_CursorB.y); - + // be a bit paranoid: + if(! firstLine || ! lastLine) + return; + // First, delete what's left of this line: MoveCursorTo(m_Selection.m_CursorA); DeleteToEndOfLine(); @@ -2682,7 +2690,7 @@ wxLayoutList::DeleteSelection(void) // Recalculate the line positions and numbers but notice that firstLine // might not exist any more - it could be deleted by Delete(1) above wxLayoutLine *firstLine2 = prevLine ? prevLine->GetNextLine() : m_FirstLine; - firstLine2->RecalculatePositions(1, this); + firstLine2->MarkDirty(); } /// Starts highlighting the selection @@ -2708,6 +2716,37 @@ wxLayoutList::EndHighlighting(wxDC &dc) } +wxLayoutLine * +wxLayoutList::GetLine(CoordType index) const +{ + wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines), + "invalid index" ); + + wxLayoutLine *line; + CoordType n = index; +#ifdef DEBUG + CoordType lineNo = 0; +#endif + + for ( line = m_FirstLine; line && n-- > 0; line = + line->GetNextLine() ) + { +#ifdef DEBUG +wxASSERT(line->GetLineNumber() == lineNo ); + lineNo++; +#endif +} + + if ( line ) + { + // should be the right one + wxASSERT( line->GetLineNumber() == index ); + } + + return line; +} + + wxLayoutList * wxLayoutList::Copy(const wxPoint &from, const wxPoint &to) @@ -2782,15 +2821,15 @@ wxLayoutList::GetSelection(wxLayoutDataObject *wxlo, bool invalidate) { wxString string; - wxLayoutExportObject *export; + wxLayoutExportObject *exp; wxLayoutExportStatus status(llist); - while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL) + while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_OBJECTS)) != NULL) { - if(export->type == WXLO_EXPORT_EMPTYLINE) + if(exp->type == WXLO_EXPORT_EMPTYLINE) ; //FIXME missing support for linebreaks in string format else - export->content.object->Write(string); - delete export; + exp->content.object->Write(string); + delete exp; } wxlo->SetData(string.c_str(), string.Length()+1); @@ -2861,6 +2900,9 @@ wxLayoutPrintout::wxLayoutPrintout(wxLayoutList *llist, // remove any highlighting which could interfere with printing: m_llist->StartSelection(); m_llist->EndSelection(); + // force a full layout of the list: + m_llist->ForceTotalLayout(); + // layout is called in ScaleDC() when we have a DC } wxLayoutPrintout::~wxLayoutPrintout() @@ -2927,14 +2969,15 @@ bool wxLayoutPrintout::OnPrintPage(int page) { int top, bottom; top = (page - 1)*m_PrintoutHeight; - bottom = top + m_PrintoutHeight; + bottom = top + m_PrintoutHeight; WXLO_DEBUG(("OnPrintPage(%d) printing from %d to %d", page, top, bottom)); // SetDeviceOrigin() doesn't work here, so we need to manually // translate all coordinates. wxPoint translate(m_Offset.x,m_Offset.y-top); - m_llist->Draw(*dc, translate, top, bottom); + m_llist->Draw(*dc, translate, top, bottom, TRUE /* clip strictly + */); return true; } else @@ -2947,14 +2990,19 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, determine the correct paper size and scaling. We don't actually print anything on it. */ #ifdef __WXMSW__ - wxPrinterDC psdc("","",WXLLIST_TEMPFILE,false); + wxPrinterDC *psdc = new wxPrinterDC("","",WXLLIST_TEMPFILE,false); #else - wxPostScriptDC psdc(WXLLIST_TEMPFILE,false); + wxPostScriptDC *psdc = new wxPostScriptDC(WXLLIST_TEMPFILE,false); #endif - float scale = ScaleDC(&psdc); + psdc->StartDoc(m_title); + // before we draw anything, me must make sure the list is properly + // laid out + m_llist->Layout(*psdc); + + float scale = ScaleDC(psdc); - psdc.GetSize(&m_PageWidth, &m_PageHeight); + psdc->GetSize(&m_PageWidth, &m_PageHeight); // This sets a left/top origin of 15% and 5%: m_Offset = wxPoint((15*m_PageWidth)/100, (5*m_PageHeight)/100); @@ -2962,14 +3010,6 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, // This is the length of the printable area. m_PrintoutHeight = m_PageHeight - 2*m_Offset.y; m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height -#if 0 - // We should really use the margin settings of wxWindows somehow. - m_Offset = wxPoint(0,0); - // This is the length of the printable area. - m_PrintoutHeight = m_PageHeight; - m_PrintoutHeight = (int)( m_PrintoutHeight / scale); // we want to use the real paper height -#endif - m_NumOfPages = 1 + (int)( m_llist->GetSize().y / (float)(m_PrintoutHeight)); @@ -2979,6 +3019,8 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, *selPageFrom = 1; *selPageTo = m_NumOfPages; + psdc->EndDoc(); + delete psdc; wxRemoveFile(WXLLIST_TEMPFILE); } diff --git a/samples/richedit/wxllist.h b/samples/richedit/wxllist.h index 071f490dbf..940e3aca6b 100644 --- a/samples/richedit/wxllist.h +++ b/samples/richedit/wxllist.h @@ -1,7 +1,7 @@ /*-*- c++ -*-******************************************************** * wxLayoutList.h - a formatted text rendering engine for wxWindows * * * - * (C) 1999 by Karsten Ballüder (Ballueder@usa.net) * + * (C) 1999 by Karsten Ballüder (ballueder@gmx.net) * * * * $Id$ *******************************************************************/ @@ -28,6 +28,8 @@ # define WXMENU_LAYOUT_LCLICK 1111 # define WXMENU_LAYOUT_RCLICK 1112 # define WXMENU_LAYOUT_DBLCLICK 1113 +#else // for Mahogany only: +# include "MObject.h" #endif // use the wxWindows caret class instead of home grown cursor whenever possible @@ -96,6 +98,9 @@ class WXDLLEXPORT wxFont; its size. */ class wxLayoutObject +#ifdef M_BASEDIR + : public MObject +#endif { public: /** This structure can be used to contain data associated with the @@ -210,6 +215,9 @@ public: protected: /// optional data for application's use UserData *m_UserData; +#if defined (M_BASEDIR) && defined (DEBUG) + MOBJECT_NAME(wxLayoutObject) +#endif }; /// Define a list type of wxLayoutObject pointers. @@ -640,15 +648,6 @@ public: CoordType GetHeight(void) const { return m_Height; } /// Returns the width of this line. CoordType GetWidth(void) const { return m_Width; } - /** This will recalculate the position and size of this line. - If called recursively it will abort if the position of an - object is unchanged, assuming that none of the following - objects need to move. - @param recurse if greater 0 then it will be used as the - minimum(!) recursion level, continue with all lines till the end of - the list or until the coordinates no longer changed. - */ - void RecalculatePositions(int recurse, wxLayoutList *llist); /// Recalculates the position of this line on the canvas. wxPoint RecalculatePosition(wxLayoutList *llist); @@ -681,10 +680,6 @@ public: m_Dirty = true; } - /** Marks the following lines as dirty. - @param recurse if -1 recurse to end of list, otherwise depth of recursion. - */ - void MarkNextDirty(int recurse = 0); /// Reset the dirty flag void MarkClean() { m_Dirty = false; m_updateLeft = -1; } @@ -699,17 +694,10 @@ private: @param height new height */ void SetHeight(CoordType height, wxLayoutList *llist) - { m_Height = height; RecalculatePositions(true, llist); } + { m_Height = height; MarkDirty(); } - /** Moves the linenumbers one on, because a line has been inserted - or deleted. - @param delta either +1 or -1 - */ - void MoveLines(int delta) - { - m_LineNumber += delta; - if(m_Next) m_Next->MoveLines(delta); - } + /** Updates the line numbers. */ + void ReNumber(void); //@} private: /// The line number. @@ -776,6 +764,14 @@ public: /// Empty: clear the list but leave font settings. void Empty(void); + /** Enable or disable auto-formatting. Normally, while editing this + should be enabled which is the default. While + inserting/deleting lots of text, it makes sense to temporarily + disable this. + @param enable TRUE to enable, FALSE to disable + */ + void SetAutoFormatting(bool enable = TRUE) + { m_AutoFormat = enable; } /**@name Cursor Management */ //@{ /** Set new cursor position. @@ -971,10 +967,13 @@ public: @param offset an optional offset to shift printout @param top optional y coordinate where to start drawing @param bottom optional y coordinate where to stop drawing + @param clipStrictly if set, do not draw objects which reach + beyond "bottom". Set this when printing. */ void Draw(wxDC &dc, const wxPoint &offset = wxPoint(0,0), - CoordType top = -1, CoordType bottom = -1); + CoordType top = -1, CoordType bottom = -1, + bool clipStrictly = false); /** Calculates new layout for the list, like Draw() but does not actually draw it. @@ -989,6 +988,13 @@ public: wxPoint *cpos = NULL, wxPoint *csize = NULL); + /** Ensure that the whole list will be recalculate on the next call + to Layout() or Draw(). + @param redrawAll TRUE or FALSE to reset it + */ + void ForceTotalLayout(bool redrawAll = TRUE) + { m_ReLayoutAll = redrawAll; } + /** Returns the screen coordinates relating to a given cursor position and the size of the cursor at that position. @param dc for which to calculate it @@ -1014,9 +1020,8 @@ public: wxPoint GetSize(void) const; /** Returns the cursor position on the screen. - @return cursor position in pixels */ - wxPoint GetCursorScreenPos(wxDC &dc); + wxPoint GetCursorScreenPos(void) const; /** Draws the cursor. @param active If true, draw a bold cursor to mark window as @@ -1134,25 +1139,7 @@ public: void DecNumLines() { m_numLines--; } /// get the line by number - wxLayoutLine *GetLine(CoordType index) const - { - wxASSERT_MSG( (0 <= index) && (index < (CoordType)m_numLines), - "invalid index" ); - - wxLayoutLine *line; - CoordType n = index; - for ( line = m_FirstLine; line && n-- > 0; line = line->GetNextLine() ) - ; - - if ( line ) - { - // should be the right one - wxASSERT( line->GetLineNumber() == index ); - } - - return line; - } - + wxLayoutLine *GetLine(CoordType index) const; private: /// Clear the list. void InternalClear(void); @@ -1167,6 +1154,10 @@ private: /// Is the update rectangle valid? bool m_UpdateRectValid; + /// Shall we auto-format? + bool m_AutoFormat; + /// Shall we re-layout everything? + bool m_ReLayoutAll; /**@name Cursor Management */ //@{ /// Where the text cursor (column,line) is. diff --git a/samples/richedit/wxlparser.cpp b/samples/richedit/wxlparser.cpp index b3a961e374..1089a45885 100644 --- a/samples/richedit/wxlparser.cpp +++ b/samples/richedit/wxlparser.cpp @@ -178,7 +178,7 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status, int mode, int flags) { wxASSERT(status); - wxLayoutExportObject * export; + wxLayoutExportObject * exp; if(status->m_iterator == NULLIT) // end of line { @@ -186,29 +186,29 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status, // reached end of list return NULL; } - export = new wxLayoutExportObject(); + exp = new wxLayoutExportObject(); wxLayoutObjectType type; if(status->m_iterator != NULLIT) { type = (** status->m_iterator).GetType(); if( mode == WXLO_EXPORT_AS_OBJECTS || ! WXLO_IS_TEXT(type)) // simple case { - export->type = WXLO_EXPORT_OBJECT; - export->content.object = *status->m_iterator; + exp->type = WXLO_EXPORT_OBJECT; + exp->content.object = *status->m_iterator; status->m_iterator++; - return export; + return exp; } } else { // iterator == NULLIT if(mode == WXLO_EXPORT_AS_OBJECTS) { - export->type = WXLO_EXPORT_EMPTYLINE; - export->content.object = NULL; //empty line + exp->type = WXLO_EXPORT_EMPTYLINE; + exp->content.object = NULL; //empty line status->m_line = status->m_line->GetNextLine(); if(status->m_line) status->m_iterator = status->m_line->GetFirstObject(); - return export; + return exp; } else type = WXLO_TYPE_TEXT; @@ -254,9 +254,9 @@ wxLayoutExportObject *wxLayoutExport(wxLayoutExportStatus *status, status->m_iterator++; } - export->type = (mode == WXLO_EXPORT_AS_HTML) + exp->type = (mode == WXLO_EXPORT_AS_HTML) ? WXLO_EXPORT_HTML : WXLO_EXPORT_TEXT; - export->content.text = str; - return export; + exp->content.text = str; + return exp; } diff --git a/samples/richedit/wxlwindow.cpp b/samples/richedit/wxlwindow.cpp index 63ce2369cf..c2c73c171c 100644 --- a/samples/richedit/wxlwindow.cpp +++ b/samples/richedit/wxlwindow.cpp @@ -1,7 +1,7 @@ /*-*- c++ -*-******************************************************** * wxLwindow.h : a scrolled Window for displaying/entering rich text* * * - * (C) 1998, 1999 by Karsten Ballüder (Ballueder@usa.net) * + * (C) 1998, 1999 by Karsten Ballüder (karsten@phy.hw.ac.uk) * * * * $Id$ *******************************************************************/ @@ -34,6 +34,9 @@ # endif // USE_PCH # include "gui/wxlwindow.h" # include "gui/wxlparser.h" + +# include "MDialogs.h" +# include "strutil.h" #else # ifdef __WXMSW__ # include @@ -57,7 +60,7 @@ // macros // ---------------------------------------------------------------------------- -#ifdef WXLAYOUT_DEBUG +#ifdef DEBUG # define WXLO_DEBUG(x) wxLogDebug x #else # define WXLO_DEBUG(x) @@ -75,6 +78,10 @@ #define WXLO_ROFFSET 20 #define WXLO_BOFFSET 20 +/// scroll margins when selecting with the mouse +#define WXLO_SCROLLMARGIN_X 10 +#define WXLO_SCROLLMARGIN_Y 10 + /// the size of one scrollbar page in pixels static const int X_SCROLL_PAGE = 10; static const int Y_SCROLL_PAGE = 20; @@ -105,6 +112,8 @@ BEGIN_EVENT_TABLE(wxLayoutWindow,wxScrolledWindow) EVT_SET_FOCUS(wxLayoutWindow::OnSetFocus) EVT_KILL_FOCUS(wxLayoutWindow::OnKillFocus) + +// EVT_IDLE(wxLayoutWindow::ResizeScrollbars) END_EVENT_TABLE() // ---------------------------------------------------------------------------- @@ -119,7 +128,7 @@ static bool IsDirectionKey(long keyCode); // ============================================================================ #ifndef wxWANTS_CHARS - #define wxWANTS_CHARS 0 +# define wxWANTS_CHARS 0 #endif // ---------------------------------------------------------------------------- @@ -146,6 +155,9 @@ wxLayoutWindow::wxLayoutWindow(wxWindow *parent) m_llist = new wxLayoutList(); m_BGbitmap = NULL; m_ScrollToCursor = false; +#ifndef __WXMSW__ + m_FocusFollowMode = false; +#endif SetWrapMargin(0); // no scrollbars initially @@ -194,8 +206,7 @@ wxLayoutWindow::Clear(int family, wxScrolledWindow::Clear(); ResizeScrollbars(true); SetDirty(); - SetModified(false); - + SetModified(FALSE); if ( m_Editable ) m_CursorVisibility = 1; @@ -204,15 +215,12 @@ wxLayoutWindow::Clear(int family, GetCaret()->Show(); #endif // WXLAYOUT_USE_CARET - DoPaint((wxRect *)NULL); + RequestUpdate((wxRect *)NULL); } void wxLayoutWindow::Refresh(bool eraseBackground, const wxRect *rect) { wxScrolledWindow::Refresh(eraseBackground, rect); - - ResizeScrollbars(); -//FIXME is this needed? It causes problems... ScrollToCursor(); } void @@ -220,15 +228,12 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) { wxClientDC dc( this ); PrepareDC( dc ); -#ifdef __WXMSW__ - if ( eventId != WXLOWIN_MENU_MOUSEMOVE ) + if ( eventId != WXLOWIN_MENU_MOUSEMOVE +#ifndef __WXMSW__ + || m_FocusFollowMode #endif - { - // moving the mouse in a window shouldn't give it the focus! - // Oh yes! wxGTK's focus handling is so broken, that this is the - // only sensible way to go. + ) SetFocus(); - } wxPoint findPos; findPos.x = dc.DeviceToLogicalX(event.GetX()); @@ -238,12 +243,43 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) findPos.y -= WXLO_YOFFSET; if(findPos.x < 0) - findPos.x = 0; + findPos.x = 0; if(findPos.y < 0) - findPos.y = 0; + findPos.y = 0; m_ClickPosition = wxPoint(event.GetX(), event.GetY()); + // Scroll the window if the mouse is at the end of it: + if(m_Selecting && eventId == WXLOWIN_MENU_MOUSEMOVE) + { + //WXLO_DEBUG(("selecting at : %d/%d", (int) event.GetX(), (int)event.GetY())); + int left, top; + ViewStart(&left, &top); + wxSize size = GetClientSize(); + int xdelta, ydelta; + + if(event.GetX() < WXLO_SCROLLMARGIN_X) + xdelta = -(WXLO_SCROLLMARGIN_X-event.GetX()); + else if(event.GetX() > size.x-WXLO_SCROLLMARGIN_X) + xdelta = event.GetX()-size.x+WXLO_SCROLLMARGIN_X; + else + xdelta = 0; + if(event.GetY() < WXLO_SCROLLMARGIN_Y) + ydelta = -(WXLO_SCROLLMARGIN_Y-event.GetY()); + else if(event.GetY() > size.y-WXLO_SCROLLMARGIN_Y) + ydelta = event.GetY()-size.y+WXLO_SCROLLMARGIN_Y; + else + ydelta = 0; + + //WXLO_DEBUG(("xdelta: %d", (int) xdelta)); + if(xdelta != 0 || ydelta != 0) + { + top += ydelta; if(top < 0) top = 0; + left += xdelta; if(left < 0) left = 0; + Scroll(left, top); + } + } + wxPoint cursorPos; bool found; wxLayoutObject *obj = m_llist->FindObjectScreen(dc, findPos, @@ -253,141 +289,132 @@ wxLayoutWindow::OnMouse(int eventId, wxMouseEvent& event) // has the mouse only been moved? switch ( eventId ) { - case WXLOWIN_MENU_MOUSEMOVE: + case WXLOWIN_MENU_MOUSEMOVE: + { + // this variables is used to only erase the message in the status + // bar if we had put it there previously - otherwise empting status + // bar might be undesirable + static bool s_hasPutMessageInStatusBar = false; + + // found is only true if we are really over an object, not just + // behind it + if(found && u && ! m_Selecting) + { + if(!m_HandCursor) + SetCursor(wxCURSOR_HAND); + m_HandCursor = TRUE; + if(m_StatusBar && m_StatusFieldLabel != -1) { - // this variables is used to only erase the message in the status - // bar if we had put it there previously - otherwise empting status - // bar might be undesirable - static bool s_hasPutMessageInStatusBar = false; - - // found is only true if we are really over an object, not just - // behind it - if(found && u && ! m_Selecting) - { - if(!m_HandCursor) - SetCursor(wxCURSOR_HAND); - m_HandCursor = TRUE; - if(m_StatusBar && m_StatusFieldLabel != -1) - { - const wxString &label = u->GetLabel(); - if(label.Length()) - { - m_StatusBar->SetStatusText(label, - m_StatusFieldLabel); - s_hasPutMessageInStatusBar = true; - } - } - } - else + const wxString &label = u->GetLabel(); + if(label.Length()) { - if(m_HandCursor) - SetCursor(wxCURSOR_IBEAM); - m_HandCursor = FALSE; - if( m_StatusBar && m_StatusFieldLabel != -1 && - s_hasPutMessageInStatusBar ) - { - m_StatusBar->SetStatusText("", m_StatusFieldLabel); - } + m_StatusBar->SetStatusText(label, + m_StatusFieldLabel); + s_hasPutMessageInStatusBar = true; } } - - // selecting? - if ( event.LeftIsDown() ) + } + else + { + if(m_HandCursor) + SetCursor(wxCURSOR_IBEAM); + m_HandCursor = FALSE; + if( m_StatusBar && m_StatusFieldLabel != -1 && + s_hasPutMessageInStatusBar ) { - // m_Selecting might not be set if the button got pressed - // outside this window, so check for it: - if( m_Selecting ) - { - m_llist->ContinueSelection(cursorPos, m_ClickPosition); - DoPaint(); // TODO: we don't have to redraw everything! - } + m_StatusBar->SetStatusText("", m_StatusFieldLabel); } + } + } - if ( u ) - { - u->DecRef(); - u = NULL; - } - break; + // selecting? + if ( event.LeftIsDown() ) + { + // m_Selecting might not be set if the button got pressed + // outside this window, so check for it: + if( m_Selecting ) + { + m_llist->ContinueSelection(cursorPos, m_ClickPosition); + RequestUpdate(); // TODO: we don't have to redraw everything! + } + } - case WXLOWIN_MENU_LDOWN: - { - // always move cursor to mouse click: -// if ( obj ) - { - // we have found the real position - m_llist->MoveCursorTo(cursorPos); - } -// else -// { -// // click beyond the end of the text -// m_llist->MoveCursorToEnd(); -// } - - // clicking a mouse removes the selection - if ( m_llist->HasSelection() ) - { - m_llist->DiscardSelection(); - m_Selecting = false; - DoPaint(); // TODO: we don't have to redraw everything! - } - - // Calculate where the top of the visible area is: - int x0, y0; - ViewStart(&x0,&y0); - int dx, dy; - GetScrollPixelsPerUnit(&dx, &dy); - x0 *= dx; y0 *= dy; - - wxPoint offset(-x0+WXLO_XOFFSET, -y0+WXLO_YOFFSET); - - if(m_CursorVisibility == -1) - m_CursorVisibility = 1; + if ( u ) + { + u->DecRef(); + u = NULL; + } + break; + + case WXLOWIN_MENU_LDOWN: + { + // always move cursor to mouse click: + m_llist->MoveCursorTo(cursorPos); + + // clicking a mouse removes the selection + if ( m_llist->HasSelection() ) + { + m_llist->DiscardSelection(); + m_Selecting = false; + RequestUpdate(); // TODO: we don't have to redraw everything! + } + + // Calculate where the top of the visible area is: + int x0, y0; + ViewStart(&x0,&y0); + int dx, dy; + GetScrollPixelsPerUnit(&dx, &dy); + x0 *= dx; y0 *= dy; + + wxPoint offset(-x0+WXLO_XOFFSET, -y0+WXLO_YOFFSET); + + if(m_CursorVisibility == -1) + m_CursorVisibility = 1; #ifdef WXLAYOUT_USE_CARET - if ( m_CursorVisibility == 1 ) - GetCaret()->Show(); + if ( m_CursorVisibility == 1 ) + GetCaret()->Show(); #endif // WXLAYOUT_USE_CARET - if(m_CursorVisibility) - { - // draw a thick cursor for editable windows with focus - m_llist->DrawCursor(dc, m_HaveFocus && IsEditable(), offset); - } + if(m_CursorVisibility) + { + // draw a thick cursor for editable windows with focus + m_llist->DrawCursor(dc, m_HaveFocus && IsEditable(), offset); + } #ifdef __WXGTK__ - DoPaint(); // DoPaint suppresses flicker under GTK + RequestUpdate(); // RequestUpdate suppresses flicker under GTK #endif // wxGTK - // start selection - m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition); - m_Selecting = true; - } - break; + // start selection + m_llist->StartSelection(wxPoint(-1, -1), m_ClickPosition); + m_Selecting = true; + } + break; - case WXLOWIN_MENU_LUP: - if ( m_Selecting ) - { - m_llist->EndSelection(); - m_Selecting = false; + case WXLOWIN_MENU_LUP: + if ( m_Selecting ) + { + m_llist->EndSelection(); + m_Selecting = false; - DoPaint(); // TODO: we don't have to redraw everything! - } - break; + RequestUpdate(); // TODO: we don't have to redraw everything! + } + break; - case WXLOWIN_MENU_MDOWN: - Paste(TRUE); - break; + case WXLOWIN_MENU_MDOWN: + Paste(TRUE); + break; - case WXLOWIN_MENU_DBLCLICK: - // select a word under cursor - m_llist->MoveCursorTo(cursorPos); - m_llist->MoveCursorWord(-1); - m_llist->StartSelection(); - m_llist->MoveCursorWord(1, false); - m_llist->EndSelection(); - m_Selecting = false; - DoPaint(); // TODO: we don't have to redraw everything! - break; + case WXLOWIN_MENU_DBLCLICK: + // select a word under cursor + m_llist->MoveCursorTo(cursorPos); + m_llist->MoveCursorWord(-1); + m_llist->StartSelection(); + m_llist->MoveCursorWord(1, false); + m_llist->EndSelection(); + m_Selecting = false; + RequestUpdate(); // TODO: we don't have to redraw everything! + break; } // notify about mouse events? @@ -440,6 +467,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) { m_Selecting = false; m_llist->EndSelection(); + m_llist->DiscardSelection(); //FIXME: correct? } // If we deleted the selection here, we must not execute the @@ -455,14 +483,15 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) { m_llist->DeleteSelection(); deletedSelection = true; + SetDirty(); } // + starts selection if ( IsDirectionKey(keyCode) ) { + // just continue the old selection if ( m_Selecting ) { - // just continue the old selection if( event.ShiftDown() ) m_llist->ContinueSelection(); else @@ -476,7 +505,6 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) m_Selecting = true; m_llist->StartSelection(); } - } // If needed, make cursor visible: @@ -526,18 +554,33 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) else m_llist->MoveCursorToEndOfLine(); break; - default: - if(keyCode == 'c' && ctrlDown) - { - // this should work even in read-only mode - Copy(); - } + + if(ctrlDown && ! IsEditable()) + switch(keyCode) + { + case 'c': + // this should work even in read-only mode + Copy(); + break; +#ifdef M_BASEDIR + case 's': // search + Find(""); + break; + case 't': // search again + FindAgain(); + break; +#endif + default: + ; + } else if( IsEditable() ) { /* First, handle control keys */ if(ctrlDown && ! event.AltDown()) { + if(keyCode >= 'A' && keyCode <= 'Z') + keyCode = tolower(keyCode); switch(keyCode) { case WXK_INSERT: @@ -545,23 +588,44 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) break; case WXK_DELETE : if(! deletedSelection) + { m_llist->DeleteWord(); + SetDirty(); + } break; case 'd': if(! deletedSelection) // already done + { m_llist->Delete(1); + SetDirty(); + } break; case 'y': m_llist->DeleteLines(1); + SetDirty(); break; case 'h': // like backspace - if(m_llist->MoveCursorHorizontally(-1)) m_llist->Delete(1); + if(m_llist->MoveCursorHorizontally(-1)) + { + m_llist->Delete(1); + SetDirty(); + } + break; +#ifdef M_BASEDIR + case 's': // search + Find(""); + break; + case 't': // search again + FindAgain(); break; - case 'u': +#endif + case 'u': m_llist->DeleteToBeginOfLine(); + SetDirty(); break; case 'k': m_llist->DeleteToEndOfLine(); + SetDirty(); break; case 'v': Paste(); @@ -586,6 +650,7 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) case WXK_DELETE: case 'd': m_llist->DeleteWord(); + SetDirty(); break; default: ; @@ -605,45 +670,57 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) Cut(); else if(! deletedSelection) + { m_llist->Delete(1); + SetDirty(); + } break; case WXK_BACK: // backspace if(! deletedSelection) if(m_llist->MoveCursorHorizontally(-1)) + { m_llist->Delete(1); + SetDirty(); + } break; case WXK_RETURN: if(m_WrapMargin > 0) m_llist->WrapLine(m_WrapMargin); m_llist->LineBreak(); + SetDirty(); break; case WXK_TAB: if ( !event.ShiftDown() ) { - // TODO should be configurable - static const int tabSize = 8; + // TODO should be configurable + static const int tabSize = 8; - CoordType x = m_llist->GetCursorPos().x; - size_t numSpaces = tabSize - x % tabSize; - m_llist->Insert(wxString(' ', numSpaces)); + CoordType x = m_llist->GetCursorPos().x; + size_t numSpaces = tabSize - x % tabSize; + m_llist->Insert(wxString(' ', numSpaces)); + SetDirty(); } break; default: - if((!(event.ControlDown() || event.AltDown() || event.MetaDown())) + if((!(event.ControlDown() || event.AltDown() +//#if 0 + ///FIXME: wxGTK reports MetaDown always + || event.MetaDown() +//#endif + )) && (keyCode < 256 && keyCode >= 32) ) { if(m_WrapMargin > 0 && isspace(keyCode)) m_llist->WrapLine(m_WrapMargin); m_llist->Insert((char)keyCode); + SetDirty(); } break; } } - SetDirty(); - SetModified(); }// if(IsEditable()) }// first switch() @@ -652,14 +729,9 @@ wxLayoutWindow::OnChar(wxKeyEvent& event) // continue selection to the current (new) cursor position m_llist->ContinueSelection(); } - - // we must call ResizeScrollbars() before ScrollToCursor(), otherwise the - // ne cursor position might be outside the current scrolllbar range - ResizeScrollbars(); ScrollToCursor(); - // refresh the screen - DoPaint(m_llist->GetUpdateRect()); + RequestUpdate(m_llist->GetUpdateRect()); } void @@ -678,8 +750,9 @@ wxLayoutWindow::OnKeyUp(wxKeyEvent& event) void wxLayoutWindow::ScrollToCursor(void) { - wxClientDC dc( this ); - PrepareDC( dc ); + //is always needed to make sure we know where the cursor is + //if(IsDirty()) + RequestUpdate(m_llist->GetUpdateRect()); int x0,y0,x1,y1, dx, dy; @@ -693,13 +766,10 @@ wxLayoutWindow::ScrollToCursor(void) // Get the size of the visible window: GetClientSize(&x1, &y1); - // update the cursor screen position - m_llist->Layout(dc); - // Make sure that the scrollbars are at a position so that the cursor is // visible if we are editing WXLO_DEBUG(("m_ScrollToCursor = %d", (int) m_ScrollToCursor)); - wxPoint cc = m_llist->GetCursorScreenPos(dc); + wxPoint cc = m_llist->GetCursorScreenPos(); // the cursor should be completely visible in both directions wxPoint cs(m_llist->GetCursorSize()); @@ -723,9 +793,9 @@ wxLayoutWindow::ScrollToCursor(void) { // set new view start Scroll(nx == -1 ? -1 : (nx+dx-1)/dx, ny == -1 ? -1 : (ny+dy-1)/dy); - // avoid recursion m_ScrollToCursor = false; + RequestUpdate(); } } @@ -737,7 +807,7 @@ wxLayoutWindow::OnPaint( wxPaintEvent &WXUNUSED(event)) } void -wxLayoutWindow::DoPaint(const wxRect *updateRect) +wxLayoutWindow::RequestUpdate(const wxRect *updateRect) { #ifdef __WXGTK__ // Calling Refresh() causes bad flicker under wxGTK!!! @@ -782,10 +852,18 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) } if(IsDirty()) { + WXLO_DEBUG(("InternalPaint, isdirty, list size: %ld,%ld", + (unsigned long) m_llist->GetSize().x, + (unsigned long) m_llist->GetSize().y)); +// m_llist->ForceTotalLayout(); m_llist->Layout(dc); + WXLO_DEBUG(("InternalPaint, isdirty, list size after layout: %ld,%ld", + (unsigned long) m_llist->GetSize().x, + (unsigned long) m_llist->GetSize().y)); ResizeScrollbars(); + ResetDirty(); } - + /* Check whether the window has grown, if so, we need to reallocate the bitmap to be larger. */ if(x1 > m_bitmapSize.x || y1 > m_bitmapSize.y) @@ -881,7 +959,6 @@ wxLayoutWindow::InternalPaint(const wxRect *updateRect) #endif // WXLAYOUT_USE_CARET ResetDirty(); - m_ScrollToCursor = false; if ( m_StatusBar && m_StatusFieldCursor != -1 ) { @@ -905,9 +982,7 @@ void wxLayoutWindow::OnSize(wxSizeEvent &event) { if ( m_llist ) - { ResizeScrollbars(); - } event.Skip(); } @@ -916,6 +991,17 @@ wxLayoutWindow::OnSize(wxSizeEvent &event) void wxLayoutWindow::ResizeScrollbars(bool exact) { + + if(IsDirty()) + { + wxClientDC dc( this ); + PrepareDC( dc ); +// m_llist->ForceTotalLayout(); + m_llist->Layout(dc); + ResetDirty(); + RequestUpdate(); + } + wxPoint max = m_llist->GetSize(); wxSize size = GetClientSize(); @@ -1016,6 +1102,7 @@ wxLayoutWindow::Paste(bool primary) wxTheClipboard->GetData(&data); wxString text = data.GetText(); wxLayoutImportText( m_llist, text); + SetDirty(); } } wxTheClipboard->Close(); @@ -1039,13 +1126,13 @@ wxLayoutWindow::Copy(bool invalidate) return FALSE; // Export selection as text: wxString text; - wxLayoutExportObject *export; + wxLayoutExportObject *exp; wxLayoutExportStatus status(llist); - while((export = wxLayoutExport( &status, WXLO_EXPORT_AS_TEXT)) != NULL) + while((exp = wxLayoutExport( &status, WXLO_EXPORT_AS_TEXT)) != NULL) { - if(export->type == WXLO_EXPORT_TEXT) - text << *(export->content.text); - delete export; + if(exp->type == WXLO_EXPORT_TEXT) + text << *(exp->content.text); + delete exp; } delete llist; @@ -1080,6 +1167,7 @@ wxLayoutWindow::Cut(void) if(Copy(false)) // do not invalidate selection after copy { m_llist->DeleteSelection(); + SetDirty(); return TRUE; } else @@ -1090,16 +1178,31 @@ wxLayoutWindow::Cut(void) // searching // ---------------------------------------------------------------------------- +#ifdef M_BASEDIR bool wxLayoutWindow::Find(const wxString &needle, - wxPoint * fromWhere) + wxPoint * fromWhere, + const wxString &configPath) { wxPoint found; - + + if(needle.Length() == 0) + { + if( ! MInputBox(&m_FindString, + _("Find text"), + _(" Find:"), + this, + configPath, "") + || strutil_isempty(m_FindString)) + return true; + } + else + m_FindString = needle; + if(fromWhere == NULL) - found = m_llist->FindText(needle, m_llist->GetCursorPos()); + found = m_llist->FindText(m_FindString, m_llist->GetCursorPos()); else - found = m_llist->FindText(needle, *fromWhere); + found = m_llist->FindText(m_FindString, *fromWhere); if(found.x != -1) { if(fromWhere) @@ -1109,11 +1212,21 @@ wxLayoutWindow::Find(const wxString &needle, } m_llist->MoveCursorTo(found); ScrollToCursor(); + RequestUpdate(); return true; } return false; } + +bool +wxLayoutWindow::FindAgain(void) +{ + bool rc = Find(m_FindString); + return rc; +} +#endif + // ---------------------------------------------------------------------------- // popup menu stuff // ---------------------------------------------------------------------------- @@ -1157,21 +1270,21 @@ void wxLayoutWindow::OnMenu(wxCommandEvent& event) switch (event.GetId()) { case WXLOWIN_MENU_LARGER: - m_llist->SetFontLarger(); DoPaint(); break; + m_llist->SetFontLarger(); RequestUpdate(); break; case WXLOWIN_MENU_SMALLER: - m_llist->SetFontSmaller(); DoPaint(); break; + m_llist->SetFontSmaller(); RequestUpdate(); break; case WXLOWIN_MENU_UNDERLINE: - m_llist->ToggleFontUnderline(); DoPaint(); break; + m_llist->ToggleFontUnderline(); RequestUpdate(); break; case WXLOWIN_MENU_BOLD: - m_llist->ToggleFontWeight(); DoPaint(); break; + m_llist->ToggleFontWeight(); RequestUpdate(); break; case WXLOWIN_MENU_ITALICS: - m_llist->ToggleFontItalics(); DoPaint(); break; + m_llist->ToggleFontItalics(); RequestUpdate(); break; case WXLOWIN_MENU_ROMAN: - m_llist->SetFontFamily(wxROMAN); DoPaint(); break; + m_llist->SetFontFamily(wxROMAN); RequestUpdate(); break; case WXLOWIN_MENU_TYPEWRITER: - m_llist->SetFontFamily(wxFIXED); DoPaint(); break; + m_llist->SetFontFamily(wxFIXED); RequestUpdate(); break; case WXLOWIN_MENU_SANSSERIF: - m_llist->SetFontFamily(wxSWISS); DoPaint(); break; + m_llist->SetFontFamily(wxSWISS); RequestUpdate(); break; } } @@ -1184,7 +1297,7 @@ wxLayoutWindow::OnSetFocus(wxFocusEvent &ev) { m_HaveFocus = true; ev.Skip(); - DoPaint(); // cursor must change + RequestUpdate(); // cursor must change } void @@ -1192,7 +1305,7 @@ wxLayoutWindow::OnKillFocus(wxFocusEvent &ev) { m_HaveFocus = false; ev.Skip(); - DoPaint();// cursor must change + RequestUpdate();// cursor must change } // ---------------------------------------------------------------------------- diff --git a/samples/richedit/wxlwindow.h b/samples/richedit/wxlwindow.h index c0dbd638bb..5453903a23 100644 --- a/samples/richedit/wxlwindow.h +++ b/samples/richedit/wxlwindow.h @@ -1,7 +1,7 @@ /*-*- c++ -*-******************************************************** * wxLwindow.h : a scrolled Window for displaying/entering rich text* * * - * (C) 1998,1999 by Karsten Ballüder (Ballueder@usa.net) * + * (C) 1998-1999 by Karsten Ballüder (karsten@phy.hw.ac.uk) * * * * $Id$ *******************************************************************/ @@ -106,8 +106,15 @@ public: bool Cut(void); //@} +#ifdef M_BASEDIR + /// find string in buffer bool Find(const wxString &needle, - wxPoint * fromWhere = NULL); + wxPoint * fromWhere = NULL, + const wxString &configPath = "MsgViewFindString"); + /// find the same string again + bool FindAgain(void); +#endif + void EnablePopup(bool enable = true) { m_DoPopupMenu = enable; } @@ -120,7 +127,7 @@ public: Internally, this stores the parameter and calls a refresh on wxMSW, draws directly on wxGTK. */ - void DoPaint(const wxRect *updateRect = NULL); + void RequestUpdate(const wxRect *updateRect = NULL); /// if exact == false, assume 50% extra size for the future void ResizeScrollbars(bool exact = false); // don't change this to true! @@ -155,22 +162,9 @@ public: /// Creates a wxMenu for use as a format popup. static wxMenu * MakeFormatMenu(void); - /**@name Dirty flag handling for optimisations. */ - //@{ - /// Set dirty flag. - void SetDirty(void) { m_Dirty = true; } - /// Query whether window needs redrawing. - bool IsDirty(void) const { return m_Dirty; } - /// Reset dirty flag. - void ResetDirty(void) { m_Dirty = false; } - //@} - /// Redraws the window, used by DoPaint() or OnPaint(). + /// Redraws the window, used by RequestUpdate() or OnPaint(). void InternalPaint(const wxRect *updateRect); - /// Has list been modified/edited? - bool IsModified(void) const { return m_Modified; } - /// Mark list as modified or unchanged. - void SetModified(bool modified = true) { m_Modified = modified; } /** Tell window to update a wxStatusBar with UserData labels and cursor positions. @param bar wxStatusBar pointer @@ -184,7 +178,36 @@ public: m_StatusBar = bar; m_StatusFieldLabel = labelfield; m_StatusFieldCursor = cursorfield; } +#ifndef __WXMSW__ + /// Enable or disable focus follow mode under non-MSW + void SetFocusFollowMode(bool enable = TRUE) + { m_FocusFollowMode = enable; } +#endif + + /**@name Modified flag handling, will not get reset by list unless + in Clear() */ + //@{ + /// Set dirty flag. + void SetModified(bool modified = TRUE) { m_Modified = modified; } + /// Query whether window needs redrawing. + bool IsModified(void) const { return m_Modified; } + //@} + /**@name Dirty flag handling for optimisations. + Normally one should only need to call SetDirty(), e.g. when + manipulating the wxLayoutList directly, so the window will update + itself. ResetDirty() and IsDirty() should only be used + internally. */ + //@{ + /// Set dirty flag. + void SetDirty(void) { m_Dirty = true; m_Modified = true; } + /// Query whether window needs redrawing. + bool IsDirty(void) const { return m_Dirty; } + /// Reset dirty flag. + void ResetDirty(void) { m_Dirty = false; } + //@} + + protected: /// generic function for mouse events processing void OnMouse(int eventId, wxMouseEvent& event); @@ -237,10 +260,10 @@ private: bool m_Selecting; /// wrap margin CoordType m_WrapMargin; - /// Is list dirty (for redraws, internal use)? - bool m_Dirty; - /// Has list been edited? - bool m_Modified; + /// Has list changed since last redraw, e.g. in size? + bool m_Dirty; + /// Has the list ever been modified? + bool m_Modified; wxMemoryDC *m_memDC; wxBitmap *m_bitmap; wxPoint m_bitmapSize; @@ -256,7 +279,13 @@ private: //@{ /// Do we want to auto-replace the selection with new text? bool m_AutoDeleteSelection; - //@} +#ifndef __WXMSW__ + /// Do we want the focus to follow the mouse? + bool m_FocusFollowMode; +#endif + /// For finding text and finding it again: + wxString m_FindString; +//@} DECLARE_EVENT_TABLE() }; diff --git a/src/unix/dialup.cpp b/src/unix/dialup.cpp index 0e48912bbd..a46ef04b1e 100644 --- a/src/unix/dialup.cpp +++ b/src/unix/dialup.cpp @@ -472,36 +472,42 @@ wxDialUpManagerImpl::CheckStatusInternal(void) // This can be used under Win 9x, too! struct hostent *hp; struct sockaddr_in serv_addr; - int sockfd; m_IsOnline = 0; // assume false if((hp = gethostbyname(m_BeaconHost)) == NULL) return; // no DNS no net - - serv_addr.sin_family = hp->h_addrtype; + + serv_addr.sin_family = hp->h_addrtype; memcpy(&serv_addr.sin_addr,hp->h_addr, hp->h_length); - serv_addr.sin_port = htons(m_BeaconPort); - if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) - { + serv_addr.sin_port = htons(m_BeaconPort); + + // PING method: + + int sockfd; + if( ( sockfd = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) + { // sys_error("cannot create socket for gw"); return; } - // PING method: - - if(sendto(sockfd, "hello", strlen("hello"), /* flags */ 0, - (struct sockaddr *)&serv_addr, + + if(sendto(sockfd, "hello", + strlen("hello"), /* flags */ 0, + (struct sockaddr *) &serv_addr, sizeof(serv_addr)) == -1) + { + close(sockfd); return; -#if 0 + } +#if 0 if( connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) { //sys_error("cannot connect to server"); return; } //connected! - close(sockfd); #endif + close(sockfd); m_IsOnline = TRUE; }