X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/02fe546f1fe77a53b6de70a663113a9e22c1ccf4..c3d434725bd76bc0306b9751e722ed70bd776876:/samples/richedit/wxllist.cpp?ds=inline diff --git a/samples/richedit/wxllist.cpp b/samples/richedit/wxllist.cpp index f6b6032c9c..e4ca6a4197 100644 --- a/samples/richedit/wxllist.cpp +++ b/samples/richedit/wxllist.cpp @@ -622,20 +622,25 @@ wxLayoutObjectCmd::Layout(wxDC &dc, class wxLayoutList * llist) wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist) { - m_LineNumber = 0; m_Width = m_Height = 0; m_Length = 0; + m_updateLeft = -1; MarkDirty(0); + m_Previous = prev; m_Next = NULL; + + m_LineNumber = 0; RecalculatePosition(llist); + if(m_Previous) { - m_LineNumber = m_Previous->GetLineNumber()+1; + m_LineNumber = m_Previous->GetLineNumber() + 1; m_Next = m_Previous->GetNextLine(); m_Previous->m_Next = this; } + if(m_Next) { m_Next->m_Previous = this; @@ -644,6 +649,8 @@ wxLayoutLine::wxLayoutLine(wxLayoutLine *prev, wxLayoutList *llist) } m_StyleInfo = llist->GetDefaultStyleInfo(); + + llist->IncNumLines(); } wxLayoutLine::~wxLayoutLine() @@ -734,30 +741,45 @@ wxLayoutLine::FindObject(CoordType xpos, CoordType *offset) const } wxLayoutObjectList::iterator -wxLayoutLine::FindObjectScreen(wxDC &dc, +wxLayoutLine::FindObjectScreen(wxDC &dc, wxLayoutList *llist, CoordType xpos, CoordType *cxpos, bool *found) const { wxASSERT(cxpos); - wxASSERT(cxpos); + + llist->ApplyStyle(GetStyleInfo(), dc); + wxLayoutObjectList::iterator i; CoordType x = 0, cx = 0, width; for(i = m_ObjectList.begin(); i != NULLIT; i++) { - width = (**i).GetWidth(); + wxLayoutObject *obj = *i; + if ( obj->GetType() == WXLO_TYPE_CMD ) + { + // this will set the correct font for the objects which follow + obj->Layout(dc, llist); + } + + width = obj->GetWidth(); if( x <= xpos && xpos <= x + width ) { - *cxpos = cx + (**i).GetOffsetScreen(dc, xpos-x); - if(found) *found = true; + *cxpos = cx + obj->GetOffsetScreen(dc, xpos-x); + + if ( found ) + *found = true; return i; } - x += (**i).GetWidth(); - cx += (**i).GetLength(); + + x += obj->GetWidth(); + cx += obj->GetLength(); } + // behind last object: *cxpos = cx; - if(found) *found = false; + + if (found) + *found = false; return m_ObjectList.tail(); } @@ -1004,12 +1026,24 @@ wxLayoutLine::DeleteWord(CoordType xpos) wxLayoutLine * wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist) { - if(m_Next) m_Next->m_Previous = m_Previous; - if(m_Previous) m_Previous->m_Next = m_Next; + // maintain linked list integrity + if(m_Next) + m_Next->m_Previous = m_Previous; + 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) { - m_Next->MoveLines(-1); - m_Next->RecalculatePositions(1, llist); + if ( next ) + next->RecalculatePositions(1, llist); + /* 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. */ @@ -1019,8 +1053,11 @@ wxLayoutLine::DeleteLine(bool update, wxLayoutList *llist) ) MarkNextDirty(-1); } - wxLayoutLine *next = m_Next; + delete this; + + llist->DecNumLines(); + return next; } @@ -1358,6 +1395,8 @@ wxLayoutLine::MergeNextLine(wxLayoutList *llist) #endif // 0 } + llist->DecNumLines(); + delete oldnext; } @@ -1513,6 +1552,7 @@ wxLayoutList::wxLayoutList() m_caret = NULL; #endif // WXLAYOUT_USE_CARET + m_numLines = 0; m_FirstLine = NULL; InvalidateUpdateRect(); Clear(); @@ -1521,7 +1561,10 @@ wxLayoutList::wxLayoutList() wxLayoutList::~wxLayoutList() { InternalClear(); + Empty(); m_FirstLine->DeleteLine(false, this); + + wxASSERT_MSG( m_numLines == 0, "line count calculation broken" ); } void @@ -1543,7 +1586,6 @@ wxLayoutList::Empty(void) void wxLayoutList::InternalClear(void) { - Empty(); m_Selection.m_selecting = false; m_Selection.m_valid = false; @@ -1608,6 +1650,11 @@ wxLayoutList::Clear(int family, int size, int style, int weight, m_DefaultStyleInfo = wxLayoutStyleInfo(family, size, style, weight, underline, fg, bg); m_CurrentStyleInfo = m_DefaultStyleInfo; + + // Empty() should be called after we set m_DefaultStyleInfo because + // otherwise the style info for the first line (created in Empty()) would be + // incorrect + Empty(); } wxPoint @@ -1775,14 +1822,53 @@ wxLayoutList::MoveCursorWord(int n, bool untilNext) CoordType moveDistance = 0; CoordType offset; - for ( wxLOiterator i = m_CursorLine->FindObject(m_CursorPos.x, &offset); + wxLayoutLine *lineCur = m_CursorLine; + for ( wxLOiterator i = lineCur->FindObject(m_CursorPos.x, &offset); n != 0; n > 0 ? i++ : i-- ) { if ( i == NULLIT ) - return false; + { + if ( n > 0 ) + { + // moving forward, pass to the first object of the next line + moveDistance++; + lineCur = lineCur->GetNextLine(); + if ( lineCur ) + i = lineCur->GetFirstObject(); + } + else + { + // moving backwards, pass to the last object of the prev line + moveDistance--; + lineCur = lineCur->GetPreviousLine(); + if ( lineCur ) + i = lineCur->GetLastObject(); + } + + if ( i == NULLIT ) + { + // moved to the end/beginning of text + return false; + } + + offset = -1; + } wxLayoutObject *obj = *i; + + if ( offset == -1 ) + { + // calculate offset: we are either at the very beginning or the very + // end of the object, so it isn't very difficult (the only time when + // offset is != -1 is for the very first iteration when its value is + // returned by FindObject) + if ( n > 0 ) + offset = 0; + else + offset = obj->GetLength(); + } + if( obj->GetType() != WXLO_TYPE_TEXT ) { // any visible non text objects count as one word @@ -1805,9 +1891,11 @@ wxLayoutList::MoveCursorWord(int n, bool untilNext) if ( n > 0 ) { // can't move further in this text object - n--; - canAdvance = false; + + // still should move over the object border + moveDistance++; + n--; } else if ( offset > 0 ) { @@ -1859,14 +1947,26 @@ wxLayoutList::MoveCursorWord(int n, bool untilNext) } } - n > 0 ? n-- : n++; + CoordType moveDelta = p - start - offset; + if ( (n < 0) && (offset == tobj->GetLength() - 1) ) + { + // because we substracted 1 from offset in this case above, now + // compensate for it + moveDelta--; + } + + if ( moveDelta != 0 ) + { + moveDistance += moveDelta; - moveDistance = p - start - offset; + n > 0 ? n-- : n++; + } } } - // except for the first iteration, offset is 0 - offset = 0; + // except for the first iteration, offset is calculated in the beginning + // of the loop + offset = -1; } MoveCursorHorizontally(moveDistance); @@ -1940,7 +2040,6 @@ bool wxLayoutList::LineBreak(void) { wxASSERT(m_CursorLine); - bool setFirst = (m_CursorLine == m_FirstLine && m_CursorPos.x == 0); AddCursorPosToUpdateRect(); @@ -1951,14 +2050,12 @@ wxLayoutList::LineBreak(void) height = m_CursorLine->GetHeight(); m_CursorLine = m_CursorLine->Break(m_CursorPos.x, this); - if(setFirst) // we were at beginning of first line + if(m_CursorLine->GetPreviousLine() == NULL) m_FirstLine = m_CursorLine; - wxASSERT(m_FirstLine); - if(m_CursorPos.x != 0) + if(m_CursorPos.x > 0) m_CursorPos.y++; m_CursorPos.x = 0; - // The following code will produce a height which is guaranteed to // be too high: old lineheight + the height of both new lines. // We can probably drop the old line height and start with height = @@ -2248,17 +2345,19 @@ wxLayoutList::Draw(wxDC &dc, { // only draw if between top and bottom: if((top == -1 || - line->GetPosition().y + line->GetHeight() >= top)) + line->GetPosition().y + line->GetHeight() > top)) { // if(! style_set) { ApplyStyle(line->GetStyleInfo(), dc); style_set = true; } + // little condition to speed up redrawing: + if(bottom != -1 + && line->GetPosition().y+line->GetHeight() >= bottom) + break; line->Draw(dc, this, offset); } - // little condition to speed up redrawing: - if(bottom != -1 && line->GetPosition().y > bottom) break; line = line->GetNextLine(); } InvalidateUpdateRect(); @@ -2275,7 +2374,9 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, bool *found) { // First, find the right line: - wxLayoutLine *line = m_FirstLine; + wxLayoutLine + *line = m_FirstLine, + *lastline = m_FirstLine; wxPoint p; ApplyStyle(m_DefaultStyleInfo, dc); @@ -2284,28 +2385,30 @@ wxLayoutList::FindObjectScreen(wxDC &dc, wxPoint const pos, p = line->GetPosition(); if(p.y <= pos.y && p.y+line->GetHeight() >= pos.y) break; -#if 0 - // we need to run a layout here to get font sizes right :-( - - // VZ: we can't call Layout() from here because it marks the line as - // clean and it is not refreshed when it's called from wxLayoutList:: - // Layout() - if we really need to do this, we should introduce an - // extra argument to Layout() to prevent the line from MarkClean()ing - // itself here - line->Layout(dc, this); -#endif + lastline = line; line = line->GetNextLine(); } - if(line == NULL) + + bool didFind = line != NULL; + + if ( !line ) { - if(found) *found = false; - return NULL; // not found + // use the last line: + line = lastline; } - if(cursorPos) cursorPos->y = line->GetLineNumber(); + + if ( cursorPos ) + cursorPos->y = line->GetLineNumber(); + + bool foundinline = true; // Now, find the object in the line: - wxLOiterator i = line->FindObjectScreen(dc, pos.x, - cursorPos ? & cursorPos->x : NULL , - found); + wxLOiterator i = line->FindObjectScreen(dc, this, + pos.x, + cursorPos ? &cursorPos->x : NULL, + &foundinline); + if ( found ) + *found = didFind && foundinline; + return (i == NULLIT) ? NULL : *i; } @@ -2374,10 +2477,10 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) #else // !WXLAYOUT_USE_CARET dc.SetBrush(*wxWHITE_BRUSH); //FIXME: wxGTK XOR is borken at the moment!!!dc.SetLogicalFunction(wxXOR); - dc.SetLogicalFunction(wxXOR); dc.SetPen(wxPen(*wxBLACK,1,wxSOLID)); if(active) { + dc.SetLogicalFunction(wxXOR); dc.DrawRectangle(coords.x, coords.y, m_CursorSize.x, m_CursorSize.y); SetUpdateRect(coords.x, coords.y); @@ -2385,6 +2488,7 @@ wxLayoutList::DrawCursor(wxDC &dc, bool active, wxPoint const &translate) } else { + dc.SetLogicalFunction(wxCOPY); dc.DrawLine(coords.x, coords.y+m_CursorSize.y-1, coords.x, coords.y); SetUpdateRect(coords.x, coords.y+m_CursorSize.y-1); @@ -2556,44 +2660,29 @@ wxLayoutList::DeleteSelection(void) return; } + // We now know that the two lines are different: wxLayoutLine - * firstLine = NULL, - * lastLine = NULL; - - for(firstLine = m_FirstLine; - firstLine && firstLine->GetLineNumber() < m_Selection.m_CursorA.y; - firstLine=firstLine->GetNextLine()) - ; - if(!firstLine || firstLine->GetLineNumber() != m_Selection.m_CursorA.y) - return; - - - for(lastLine = m_FirstLine; - lastLine && lastLine->GetLineNumber() < m_Selection.m_CursorB.y; - lastLine=lastLine->GetNextLine()) - ; - if(!lastLine || lastLine->GetLineNumber() != m_Selection.m_CursorB.y) - return; - - - // We now know that the two lines are different: + * firstLine = GetLine(m_Selection.m_CursorA.y), + * lastLine = GetLine(m_Selection.m_CursorB.y); // First, delete what's left of this line: MoveCursorTo(m_Selection.m_CursorA); DeleteToEndOfLine(); - wxLayoutLine *nextLine = firstLine->GetNextLine(); + wxLayoutLine *prevLine = firstLine->GetPreviousLine(), + *nextLine = firstLine->GetNextLine(); while(nextLine && nextLine != lastLine) nextLine = nextLine->DeleteLine(false, this); // Now nextLine = lastLine; Delete(1); // This joins firstLine and nextLine - Delete(m_Selection.m_CursorB.x); // This deletes the first x - // positions + Delete(m_Selection.m_CursorB.x); // This deletes the first x positions - /// Recalculate: - firstLine->RecalculatePositions(1, this); + // 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); } /// Starts highlighting the selection @@ -2839,6 +2928,9 @@ bool wxLayoutPrintout::OnPrintPage(int page) int top, bottom; top = (page - 1)*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); @@ -2863,13 +2955,21 @@ void wxLayoutPrintout::GetPageInfo(int *minPage, int *maxPage, int *selPageFrom, float scale = ScaleDC(&psdc); psdc.GetSize(&m_PageWidth, &m_PageHeight); - // This sets a left/top origin of 15% and 20%: - m_Offset = wxPoint((15*m_PageWidth)/100, m_PageHeight/20); + + // This sets a left/top origin of 15% and 5%: + m_Offset = wxPoint((15*m_PageWidth)/100, (5*m_PageHeight)/100); // This is the length of the printable area. - m_PrintoutHeight = m_PageHeight - (int) (m_PageHeight * 0.15); + 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));