Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
300db376
Commit
300db376
authored
Aug 07, 2008
by
Dylan Smith
Committed by
Alexandre Julliard
Aug 18, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
richedit: Each cell can contain multiple paragraphs in msftedit.
parent
bc61a637
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1272 additions
and
239 deletions
+1272
-239
caret.c
dlls/riched20/caret.c
+135
-16
editor.c
dlls/riched20/editor.c
+212
-23
editor.h
dlls/riched20/editor.h
+9
-1
editstr.h
dlls/riched20/editstr.h
+40
-15
list.c
dlls/riched20/list.c
+14
-1
paint.c
dlls/riched20/paint.c
+86
-31
para.c
dlls/riched20/para.c
+113
-5
rtf.h
dlls/riched20/rtf.h
+8
-0
run.c
dlls/riched20/run.c
+7
-3
table.c
dlls/riched20/table.c
+445
-97
undo.c
dlls/riched20/undo.c
+30
-2
wrap.c
dlls/riched20/wrap.c
+107
-22
writer.c
dlls/riched20/writer.c
+66
-23
No files found.
dlls/riched20/caret.c
View file @
300db376
...
...
@@ -215,7 +215,7 @@ ME_GetCursorCoordinates(ME_TextEditor *editor, ME_Cursor *pCursor,
*
height
=
pSizeRun
->
member
.
run
.
nAscent
+
pSizeRun
->
member
.
run
.
nDescent
;
*
x
=
run
->
member
.
run
.
pt
.
x
+
sz
.
cx
;
*
y
=
para
->
member
.
para
.
nYPos
+
row
->
member
.
row
.
nBaseline
+
run
->
member
.
run
.
pt
.
y
-
pSizeRun
->
member
.
run
.
nAscent
-
ME_GetYScrollPos
(
editor
);
*
y
=
para
->
member
.
para
.
pt
.
y
+
row
->
member
.
row
.
nBaseline
+
run
->
member
.
run
.
pt
.
y
-
pSizeRun
->
member
.
run
.
nAscent
-
ME_GetYScrollPos
(
editor
);
ME_DestroyContext
(
&
c
,
editor
->
hWnd
);
return
;
}
...
...
@@ -316,6 +316,28 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, int nOfs, int nChars,
}
keepFirstParaFormat
=
(
totalChars
==
nChars
&&
nChars
<=
eollen
&&
run
->
nCharOfs
);
if
(
!
editor
->
bEmulateVersion10
)
/* v4.1 */
{
ME_DisplayItem
*
next_para
=
ME_FindItemFwd
(
c
.
pRun
,
diParagraphOrEnd
);
ME_DisplayItem
*
this_para
=
next_para
->
member
.
para
.
prev_para
;
/* The end of paragraph before a table row is only deleted if there
* is nothing else on the line before it. */
if
(
this_para
==
start_para
&&
next_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
/* If the paragraph will be empty, then it should be deleted, however
* it still might have text right now which would inherit the
* MEPF_STARTROW property if we joined it right now.
* Instead we will delete it after the preceding text is deleted. */
if
(
nOfs
>
this_para
->
member
.
para
.
nCharOfs
)
{
/* Skip this end of line. */
nChars
-=
(
eollen
<
nChars
)
?
eollen
:
nChars
;
continue
;
}
keepFirstParaFormat
=
TRUE
;
}
}
ME_JoinParagraphs
(
editor
,
ME_GetParagraph
(
c
.
pRun
),
keepFirstParaFormat
);
/* ME_SkipAndPropagateCharOffset(p->pRun, shift); */
ME_CheckCharOffsets
(
editor
);
...
...
@@ -583,7 +605,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
pos
++
;
numCR
=
1
;
numLF
=
0
;
}
tp
=
ME_SplitParagraph
(
editor
,
p
->
pRun
,
p
->
pRun
->
member
.
run
.
style
,
numCR
,
numLF
);
tp
=
ME_SplitParagraph
(
editor
,
p
->
pRun
,
p
->
pRun
->
member
.
run
.
style
,
numCR
,
numLF
,
0
);
p
->
pRun
=
ME_FindItemFwd
(
tp
,
diRun
);
end_run
=
ME_FindItemBack
(
tp
,
diRun
);
ME_ReleaseStyle
(
end_run
->
member
.
run
.
style
);
...
...
@@ -630,7 +652,8 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
assert
(
pRun
->
type
!=
diRun
&&
pRun
->
type
!=
diParagraph
);
return
FALSE
;
}
}
while
(
RUN_IS_HIDDEN
(
&
pRun
->
member
.
run
));
}
while
(
RUN_IS_HIDDEN
(
&
pRun
->
member
.
run
)
||
pRun
->
member
.
run
.
nFlags
&
MERF_HIDDEN
);
pCursor
->
pRun
=
pRun
;
if
(
pRun
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
pCursor
->
nOffset
=
0
;
...
...
@@ -656,7 +679,8 @@ ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
}
do
{
pRun
=
ME_FindItemFwd
(
pRun
,
diRun
);
}
while
(
pRun
&&
RUN_IS_HIDDEN
(
&
pRun
->
member
.
run
));
}
while
(
pRun
&&
(
RUN_IS_HIDDEN
(
&
pRun
->
member
.
run
)
||
pRun
->
member
.
run
.
nFlags
&
MERF_HIDDEN
));
if
(
pRun
)
{
pCursor
->
pRun
=
pRun
;
...
...
@@ -701,9 +725,13 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
{
if
(
cursor
->
pRun
==
pRun
&&
cursor
->
nOffset
==
0
)
{
/* Skip empty start of table row paragraph */
if
(
pOtherRun
->
member
.
para
.
prev_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
pOtherRun
=
pOtherRun
->
member
.
para
.
prev_para
;
/* Paragraph breaks are treated as separate words */
if
(
pOtherRun
->
member
.
para
.
prev_para
->
type
==
diTextStart
)
return
FALSE
;
pRun
=
ME_FindItemBack
(
pOtherRun
,
diRunOrParagraph
);
}
break
;
...
...
@@ -734,6 +762,8 @@ ME_MoveCursorWords(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs)
}
else
if
(
pOtherRun
->
type
==
diParagraph
)
{
if
(
pOtherRun
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
pOtherRun
=
pOtherRun
->
member
.
para
.
next_para
;
if
(
cursor
->
pRun
==
pRun
)
pRun
=
ME_FindItemFwd
(
pOtherRun
,
diRun
);
nOffset
=
0
;
...
...
@@ -820,6 +850,45 @@ int ME_GetCursorOfs(ME_TextEditor *editor, int nCursor)
+
pCursor
->
pRun
->
member
.
run
.
nCharOfs
+
pCursor
->
nOffset
;
}
/* Helper function for ME_FindPixelPos to find paragraph within tables */
static
ME_DisplayItem
*
ME_FindPixelPosInTableRow
(
int
x
,
int
y
,
ME_DisplayItem
*
para
)
{
ME_DisplayItem
*
cell
,
*
next_cell
;
assert
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
);
cell
=
para
->
member
.
para
.
next_para
->
member
.
para
.
pCell
;
assert
(
cell
);
/* find the cell we are in */
while
((
next_cell
=
cell
->
member
.
cell
.
next_cell
)
!=
NULL
)
{
if
(
x
<
next_cell
->
member
.
cell
.
pt
.
x
)
{
para
=
ME_FindItemFwd
(
cell
,
diParagraph
);
/* Found the cell, but there might be multiple paragraphs in
* the cell, so need to search down the cell for the paragraph. */
while
(
cell
==
para
->
member
.
para
.
pCell
)
{
if
(
y
<
para
->
member
.
para
.
pt
.
y
+
para
->
member
.
para
.
nHeight
)
{
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
return
ME_FindPixelPosInTableRow
(
x
,
y
,
para
);
else
return
para
;
}
para
=
para
->
member
.
para
.
next_para
;
}
/* Past the end of the cell, so go back to the last cell paragraph */
return
para
->
member
.
para
.
prev_para
;
}
cell
=
next_cell
;
}
/* Return table row delimiter */
para
=
ME_FindItemFwd
(
cell
,
diParagraph
);
assert
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
);
assert
(
para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLEROWDELIMITER
);
assert
(
para
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLEROWDELIMITER
);
return
para
;
}
/* Finds the run and offset from the pixel position.
*
* x & y are pixel positions in virtual coordinates into the rich edit control,
...
...
@@ -843,11 +912,15 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
for
(;
p
!=
editor
->
pBuffer
->
pLast
;
p
=
p
->
member
.
para
.
next_para
)
{
assert
(
p
->
type
==
diParagraph
);
if
(
y
<
p
->
member
.
para
.
nYPos
+
p
->
member
.
para
.
nHeight
)
if
(
y
<
p
->
member
.
para
.
pt
.
y
+
p
->
member
.
para
.
nHeight
)
{
y
-=
p
->
member
.
para
.
nYPos
;
if
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
p
=
ME_FindPixelPosInTableRow
(
x
,
y
,
p
);
y
-=
p
->
member
.
para
.
pt
.
y
;
p
=
ME_FindItemFwd
(
p
,
diStartRow
);
break
;
}
else
if
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
p
=
ME_GetTableRowEnd
(
p
);
}
}
/* find row */
...
...
@@ -855,7 +928,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
{
ME_DisplayItem
*
pp
;
assert
(
p
->
type
==
diStartRow
);
if
(
y
<
p
->
member
.
row
.
nYPos
+
p
->
member
.
row
.
nHeight
)
if
(
y
<
p
->
member
.
row
.
pt
.
y
+
p
->
member
.
row
.
nHeight
)
{
p
=
ME_FindItemFwd
(
p
,
diRun
);
break
;
...
...
@@ -911,6 +984,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
if
(
is_eol
)
*
is_eol
=
1
;
rx
=
0
;
/* FIXME not sure */
goto
found_here
;
case
diCell
:
case
diParagraph
:
case
diTextEnd
:
isExact
=
FALSE
;
...
...
@@ -1185,13 +1259,14 @@ static void
ME_MoveCursorLines
(
ME_TextEditor
*
editor
,
ME_Cursor
*
pCursor
,
int
nRelOfs
)
{
ME_DisplayItem
*
pRun
=
pCursor
->
pRun
;
ME_DisplayItem
*
pItem
;
ME_DisplayItem
*
pItem
,
*
pOldPara
,
*
pNewPara
;
int
x
=
ME_GetXForArrow
(
editor
,
pCursor
);
if
(
editor
->
bCaretAtEnd
&&
!
pCursor
->
nOffset
)
pRun
=
ME_FindItemBack
(
pRun
,
diRun
);
if
(
!
pRun
)
return
;
pOldPara
=
ME_GetParagraph
(
pRun
);
if
(
nRelOfs
==
-
1
)
{
/* start of this row */
...
...
@@ -1199,13 +1274,57 @@ ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs)
assert
(
pItem
);
/* start of the previous row */
pItem
=
ME_FindItemBack
(
pItem
,
diStartRow
);
if
(
!
pItem
)
return
;
/* row not found - ignore */
pNewPara
=
ME_GetParagraph
(
pItem
);
if
(
pOldPara
->
member
.
para
.
nFlags
&
MEPF_ROWEND
||
(
pOldPara
->
member
.
para
.
pCell
&&
pOldPara
->
member
.
para
.
pCell
!=
pNewPara
->
member
.
para
.
pCell
))
{
/* Brought out of a cell */
pNewPara
=
ME_GetTableRowStart
(
pOldPara
)
->
member
.
para
.
prev_para
;
if
(
pNewPara
->
type
==
diTextStart
)
return
;
/* At the top, so don't go anywhere. */
pItem
=
ME_FindItemFwd
(
pNewPara
,
diStartRow
);
}
if
(
pNewPara
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
/* Brought into a table row */
ME_Cell
*
cell
=
&
ME_FindItemBack
(
pNewPara
,
diCell
)
->
member
.
cell
;
while
(
x
<
cell
->
pt
.
x
&&
cell
->
prev_cell
)
cell
=
&
cell
->
prev_cell
->
member
.
cell
;
if
(
cell
->
next_cell
)
/* else - we are still at the end of the row */
pItem
=
ME_FindItemBack
(
cell
->
next_cell
,
diStartRow
);
}
}
else
{
/* start of the next row */
pItem
=
ME_FindItemFwd
(
pRun
,
diStartRow
);
if
(
!
pItem
)
return
;
/* row not found - ignore */
/* FIXME If diParagraph is before diStartRow, wrap the next paragraph?
*/
pNewPara
=
ME_GetParagraph
(
pItem
);
if
(
pOldPara
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
||
(
pOldPara
->
member
.
para
.
pCell
&&
pOldPara
->
member
.
para
.
pCell
!=
pNewPara
->
member
.
para
.
pCell
))
{
/* Brought out of a cell */
pNewPara
=
ME_GetTableRowEnd
(
pOldPara
)
->
member
.
para
.
next_para
;
if
(
pNewPara
->
type
==
diTextEnd
)
return
;
/* At the bottom, so don't go anywhere. */
pItem
=
ME_FindItemFwd
(
pNewPara
,
diStartRow
);
}
if
(
pNewPara
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
/* Brought into a table row */
ME_DisplayItem
*
cell
=
ME_FindItemFwd
(
pNewPara
,
diCell
);
while
(
cell
->
member
.
cell
.
next_cell
&&
x
>=
cell
->
member
.
cell
.
next_cell
->
member
.
cell
.
pt
.
x
)
cell
=
cell
->
member
.
cell
.
next_cell
;
pItem
=
ME_FindItemFwd
(
cell
,
diStartRow
);
}
}
if
(
!
pItem
)
{
...
...
@@ -1231,8 +1350,8 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
p
=
ME_FindItemBack
(
pRun
,
diStartRowOrParagraph
);
assert
(
p
->
type
==
diStartRow
);
yp
=
ME_FindItemBack
(
p
,
diParagraph
)
->
member
.
para
.
nYPos
;
yprev
=
ys
=
y
=
yp
+
p
->
member
.
row
.
nYPos
;
yp
=
ME_FindItemBack
(
p
,
diParagraph
)
->
member
.
para
.
pt
.
y
;
yprev
=
ys
=
y
=
yp
+
p
->
member
.
row
.
pt
.
y
;
yd
=
y
-
editor
->
sizeWindow
.
cy
;
pLast
=
p
;
...
...
@@ -1243,10 +1362,10 @@ static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor)
if
(
p
->
type
==
diParagraph
)
{
/* crossing paragraphs */
if
(
p
->
member
.
para
.
prev_para
==
NULL
)
break
;
yp
=
p
->
member
.
para
.
prev_para
->
member
.
para
.
nYPos
;
yp
=
p
->
member
.
para
.
prev_para
->
member
.
para
.
pt
.
y
;
continue
;
}
y
=
yp
+
p
->
member
.
row
.
nYPos
;
y
=
yp
+
p
->
member
.
row
.
pt
.
y
;
if
(
y
<
yd
)
break
;
pLast
=
p
;
...
...
@@ -1286,8 +1405,8 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
p
=
ME_FindItemBack
(
pRun
,
diStartRowOrParagraph
);
assert
(
p
->
type
==
diStartRow
);
yp
=
ME_FindItemBack
(
p
,
diParagraph
)
->
member
.
para
.
nYPos
;
yprev
=
ys
=
y
=
yp
+
p
->
member
.
row
.
nYPos
;
yp
=
ME_FindItemBack
(
p
,
diParagraph
)
->
member
.
para
.
pt
.
y
;
yprev
=
ys
=
y
=
yp
+
p
->
member
.
row
.
pt
.
y
;
yd
=
y
+
editor
->
sizeWindow
.
cy
;
pLast
=
p
;
...
...
@@ -1296,10 +1415,10 @@ static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor)
if
(
!
p
)
break
;
if
(
p
->
type
==
diParagraph
)
{
yp
=
p
->
member
.
para
.
nYPos
;
yp
=
p
->
member
.
para
.
pt
.
y
;
continue
;
}
y
=
yp
+
p
->
member
.
row
.
nYPos
;
y
=
yp
+
p
->
member
.
row
.
pt
.
y
;
if
(
y
>=
yd
)
break
;
pLast
=
p
;
...
...
dlls/riched20/editor.c
View file @
300db376
...
...
@@ -451,8 +451,9 @@ static void ME_RTFParAttrHook(RTF_Info *info)
switch
(
info
->
rtfMinor
)
{
case
rtfParDef
:
/* restores default paragraph attributes */
fmt
.
dwMask
=
PFM_ALIGNMENT
|
PFM_BORDER
|
PFM_LINESPACING
|
PFM_TABSTOPS
|
PFM_OFFSET
|
PFM_RIGHTINDENT
|
PFM_SPACEAFTER
|
PFM_SPACEBEFORE
|
PFM_STARTINDENT
|
PFM_TABLE
;
fmt
.
dwMask
=
PFM_ALIGNMENT
|
PFM_BORDER
|
PFM_LINESPACING
|
PFM_TABSTOPS
|
PFM_OFFSET
|
PFM_RIGHTINDENT
|
PFM_SPACEAFTER
|
PFM_SPACEBEFORE
|
PFM_STARTINDENT
;
/* TODO: numbering, shading */
fmt
.
wAlignment
=
PFA_LEFT
;
fmt
.
cTabCount
=
0
;
...
...
@@ -462,12 +463,67 @@ static void ME_RTFParAttrHook(RTF_Info *info)
fmt
.
bLineSpacingRule
=
0
;
fmt
.
dySpaceBefore
=
fmt
.
dySpaceAfter
=
0
;
fmt
.
dyLineSpacing
=
0
;
fmt
.
wEffects
&=
~
PFE_TABLE
;
if
(
!
info
->
editor
->
bEmulateVersion10
)
/* v4.1 */
{
if
(
info
->
tableDef
&&
info
->
tableDef
->
tableRowStart
&&
info
->
tableDef
->
tableRowStart
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
ME_Cursor
cursor
;
ME_DisplayItem
*
para
;
/* We are just after a table row. */
RTFFlushOutputBuffer
(
info
);
cursor
=
info
->
editor
->
pCursors
[
0
];
para
=
ME_GetParagraph
(
cursor
.
pRun
);
if
(
para
==
info
->
tableDef
->
tableRowStart
->
member
.
para
.
next_para
&&
!
cursor
.
nOffset
&&
!
cursor
.
pRun
->
member
.
run
.
nCharOfs
)
{
/* Since the table row end, no text has been inserted, and the \intbl
* control word has not be used. We can confirm that we are not in a
* table anymore.
*/
info
->
tableDef
->
tableRowStart
=
NULL
;
}
}
}
else
{
/* v1.0 - v3.0 */
fmt
.
dwMask
|=
PFM_TABLE
;
fmt
.
wEffects
&=
~
PFE_TABLE
;
}
break
;
case
rtfInTable
:
{
fmt
.
dwMask
|=
PFM_TABLE
;
fmt
.
wEffects
|=
PFE_TABLE
;
ME_Cursor
cursor
;
if
(
!
info
->
editor
->
bEmulateVersion10
)
/* v4.1 */
{
if
(
!
info
->
tableDef
||
!
info
->
tableDef
->
tableRowStart
||
info
->
tableDef
->
tableRowStart
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
RTFTable
*
tableDef
;
if
(
!
info
->
tableDef
)
{
info
->
tableDef
=
ALLOC_OBJ
(
RTFTable
);
ZeroMemory
(
info
->
tableDef
,
sizeof
(
RTFTable
));
}
tableDef
=
info
->
tableDef
;
RTFFlushOutputBuffer
(
info
);
if
(
!
tableDef
->
tableRowStart
)
{
WCHAR
endl
=
'\r'
;
cursor
=
info
->
editor
->
pCursors
[
0
];
if
(
cursor
.
nOffset
||
cursor
.
pRun
->
member
.
run
.
nCharOfs
)
ME_InsertTextFromCursor
(
info
->
editor
,
0
,
&
endl
,
1
,
info
->
style
);
}
/* FIXME: Remove the following condition once nested tables are supported */
if
(
ME_GetParagraph
(
info
->
editor
->
pCursors
[
0
].
pRun
)
->
member
.
para
.
pCell
)
break
;
tableDef
->
tableRowStart
=
ME_InsertTableRowStartFromCursor
(
info
->
editor
);
}
return
;
}
else
{
/* v1.0 - v3.0 */
fmt
.
dwMask
|=
PFM_TABLE
;
fmt
.
wEffects
|=
PFE_TABLE
;
}
break
;
}
case
rtfFirstIndent
:
...
...
@@ -669,10 +725,16 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
switch
(
info
->
rtfMinor
)
{
case
rtfRowDef
:
if
(
!
info
->
tableDef
)
{
if
(
!
info
->
tableDef
)
{
info
->
tableDef
=
ALLOC_OBJ
(
RTFTable
);
ZeroMemory
(
info
->
tableDef
,
sizeof
(
RTFTable
));
ZeroMemory
(
info
->
tableDef
,
sizeof
(
RTFTable
));
}
else
{
ZeroMemory
(
info
->
tableDef
->
cells
,
sizeof
(
info
->
tableDef
->
cells
));
info
->
tableDef
->
numCellsDefined
=
0
;
}
break
;
}
case
rtfCellPos
:
if
(
!
info
->
tableDef
)
{
...
...
@@ -683,7 +745,8 @@ static void ME_RTFTblAttrHook(RTF_Info *info)
break
;
info
->
tableDef
->
cells
[
info
->
tableDef
->
numCellsDefined
].
rightBoundary
=
info
->
rtfParam
;
{
/* Tab stops store the cell positions. */
/* Tab stops were used to store cell positions before v4.1 but v4.1
* still seems to set the tabstops without using them. */
ME_DisplayItem
*
para
=
ME_GetParagraph
(
info
->
editor
->
pCursors
[
0
].
pRun
);
PARAFORMAT2
*
pFmt
=
para
->
member
.
para
.
pFmt
;
int
cellNum
=
info
->
tableDef
->
numCellsDefined
;
...
...
@@ -704,7 +767,19 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
if
(
!
tableDef
)
break
;
RTFFlushOutputBuffer
(
info
);
{
if
(
!
info
->
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
tableDef
->
tableRowStart
)
{
if
(
tableDef
->
tableRowStart
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
ME_DisplayItem
*
para
=
tableDef
->
tableRowStart
;
para
=
para
->
member
.
para
.
next_para
;
para
=
ME_InsertTableRowStartAtParagraph
(
info
->
editor
,
para
);
tableDef
->
tableRowStart
=
para
;
}
ME_InsertTableCellFromCursor
(
info
->
editor
);
}
}
else
{
/* v1.0 - v3.0 */
ME_DisplayItem
*
para
=
ME_GetParagraph
(
info
->
editor
->
pCursors
[
0
].
pRun
);
PARAFORMAT2
*
pFmt
=
para
->
member
.
para
.
pFmt
;
if
(
pFmt
->
dwMask
&
PFM_TABLE
&&
pFmt
->
wEffects
&
PFE_TABLE
&&
...
...
@@ -718,11 +793,70 @@ static void ME_RTFSpecialCharHook(RTF_Info *info)
break
;
case
rtfRow
:
{
ME_DisplayItem
*
para
,
*
cell
,
*
run
;
int
i
;
if
(
!
tableDef
)
break
;
RTFFlushOutputBuffer
(
info
);
if
(
!
info
->
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
!
tableDef
->
tableRowStart
)
break
;
if
(
tableDef
->
tableRowStart
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
para
=
tableDef
->
tableRowStart
;
para
=
para
->
member
.
para
.
next_para
;
para
=
ME_InsertTableRowStartAtParagraph
(
info
->
editor
,
para
);
tableDef
->
tableRowStart
=
para
;
}
para
=
tableDef
->
tableRowStart
;
cell
=
ME_FindItemFwd
(
para
,
diCell
);
assert
(
cell
&&
!
cell
->
member
.
cell
.
prev_cell
);
if
(
tableDef
->
numCellsDefined
<
1
)
{
/* 2000 twips appears to be the cell size that native richedit uses
* when no cell sizes are specified. */
const
int
defaultCellSize
=
2000
;
int
nRightBoundary
=
defaultCellSize
;
cell
->
member
.
cell
.
nRightBoundary
=
nRightBoundary
;
while
(
cell
->
member
.
cell
.
next_cell
)
{
cell
=
cell
->
member
.
cell
.
next_cell
;
nRightBoundary
+=
defaultCellSize
;
cell
->
member
.
cell
.
nRightBoundary
=
nRightBoundary
;
}
para
=
ME_InsertTableCellFromCursor
(
info
->
editor
);
cell
=
para
->
member
.
para
.
pCell
;
cell
->
member
.
cell
.
nRightBoundary
=
nRightBoundary
;
}
else
{
for
(
i
=
0
;
i
<
tableDef
->
numCellsDefined
;
i
++
)
{
cell
->
member
.
cell
.
nRightBoundary
=
tableDef
->
cells
[
i
].
rightBoundary
;
cell
=
cell
->
member
.
cell
.
next_cell
;
if
(
!
cell
)
{
para
=
ME_InsertTableCellFromCursor
(
info
->
editor
);
cell
=
para
->
member
.
para
.
pCell
;
}
}
/* Cell for table row delimiter is empty */
cell
->
member
.
cell
.
nRightBoundary
=
tableDef
->
cells
[
i
-
1
].
rightBoundary
;
}
{
run
=
ME_FindItemFwd
(
cell
,
diRun
);
if
(
info
->
editor
->
pCursors
[
0
].
pRun
!=
run
||
info
->
editor
->
pCursors
[
0
].
nOffset
)
{
int
nOfs
,
nChars
;
/* Delete inserted cells that aren't defined. */
info
->
editor
->
pCursors
[
1
].
pRun
=
run
;
info
->
editor
->
pCursors
[
1
].
nOffset
=
0
;
nOfs
=
ME_GetCursorOfs
(
info
->
editor
,
1
);
nChars
=
ME_GetCursorOfs
(
info
->
editor
,
0
)
-
nOfs
;
ME_InternalDeleteText
(
info
->
editor
,
nOfs
,
nChars
,
TRUE
);
}
tableDef
->
tableRowStart
=
ME_InsertTableRowEndFromCursor
(
info
->
editor
);
}
else
{
/* v1.0 - v3.0 */
WCHAR
endl
=
'\r'
;
ME_DisplayItem
*
para
=
ME_GetParagraph
(
info
->
editor
->
pCursors
[
0
].
pRun
);
PARAFORMAT2
*
pFmt
=
para
->
member
.
para
.
pFmt
;
...
...
@@ -1128,6 +1262,8 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
if
(
!
invalidRTF
&&
!
inStream
.
editstream
->
dwError
)
{
if
(
format
&
SF_RTF
)
{
ME_DisplayItem
*
para
;
/* setup the RTF parser */
memset
(
&
parser
,
0
,
sizeof
parser
);
RTFSetEditStream
(
&
parser
,
&
inStream
);
...
...
@@ -1145,6 +1281,36 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
/* do the parsing */
RTFRead
(
&
parser
);
RTFFlushOutputBuffer
(
&
parser
);
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
parser
.
tableDef
&&
parser
.
tableDef
->
tableRowStart
)
{
/* Delete any incomplete table row at the end of the rich text. */
int
nOfs
,
nChars
;
ME_DisplayItem
*
pCell
;
para
=
parser
.
tableDef
->
tableRowStart
;
parser
.
rtfMinor
=
rtfRow
;
/* Complete the table row before deleting it.
* By doing it this way we will have the current paragraph format set
* properly to reflect that is not in the complete table, and undo items
* will be added for this change to the current paragraph format. */
ME_RTFSpecialCharHook
(
&
parser
);
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
para
=
para
->
member
.
para
.
next_para
;
}
pCell
=
para
->
member
.
para
.
pCell
;
editor
->
pCursors
[
1
].
pRun
=
ME_FindItemFwd
(
para
,
diRun
);
editor
->
pCursors
[
1
].
nOffset
=
0
;
nOfs
=
ME_GetCursorOfs
(
editor
,
1
);
nChars
=
ME_GetCursorOfs
(
editor
,
0
)
-
nOfs
;
ME_InternalDeleteText
(
editor
,
nOfs
,
nChars
,
TRUE
);
parser
.
tableDef
->
tableRowStart
=
NULL
;
}
}
ME_CheckTablesForCorruption
(
editor
);
RTFDestroy
(
&
parser
);
if
(
parser
.
lpRichEditOle
)
IRichEditOle_Release
(
parser
.
lpRichEditOle
);
...
...
@@ -1624,10 +1790,17 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
}
else
if
(
ME_ArrowKey
(
editor
,
VK_LEFT
,
FALSE
,
FALSE
))
{
/* Backspace can be grouped for a single undo */
ME_ContinueCoalescingTransaction
(
editor
);
ME_DeleteTextAtCursor
(
editor
,
1
,
1
);
ME_CommitCoalescingUndo
(
editor
);
BOOL
bDeletionSucceeded
;
/* Backspace can be grouped for a single undo */
ME_ContinueCoalescingTransaction
(
editor
);
bDeletionSucceeded
=
ME_DeleteTextAtCursor
(
editor
,
1
,
1
);
if
(
!
bDeletionSucceeded
&&
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
/* Deletion was prevented so the cursor is moved back to where it was.
* (e.g. this happens when trying to delete cell boundaries)
*/
ME_ArrowKey
(
editor
,
VK_RIGHT
,
FALSE
,
FALSE
);
}
ME_CommitCoalescingUndo
(
editor
);
}
else
return
TRUE
;
...
...
@@ -2503,10 +2676,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
if
(
p
->
type
==
diTextEnd
)
break
;
if
(
p
->
type
==
diParagraph
)
{
ypara
=
p
->
member
.
para
.
nYPos
;
ypara
=
p
->
member
.
para
.
pt
.
y
;
continue
;
}
ystart
=
ypara
+
p
->
member
.
row
.
nYPos
;
ystart
=
ypara
+
p
->
member
.
row
.
pt
.
y
;
yend
=
ystart
+
p
->
member
.
row
.
nHeight
;
if
(
y
<
yend
)
{
break
;
...
...
@@ -2572,7 +2745,7 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
nPos
=
ME_GetYScrollPos
(
editor
);
row
=
ME_RowStart
(
editor
->
pCursors
[
0
].
pRun
);
para
=
ME_GetParagraph
(
row
);
top
=
para
->
member
.
para
.
nYPos
+
row
->
member
.
row
.
nYPos
;
top
=
para
->
member
.
para
.
pt
.
y
+
row
->
member
.
row
.
pt
.
y
;
bottom
=
top
+
row
->
member
.
row
.
nHeight
;
if
(
top
<
nPos
)
/* caret above window */
...
...
@@ -3089,10 +3262,10 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
assert
(
pRun
->
type
==
diRun
);
pt
.
y
=
pRun
->
member
.
run
.
pt
.
y
;
pt
.
x
=
pRun
->
member
.
run
.
pt
.
x
+
ME_PointFromChar
(
editor
,
&
pRun
->
member
.
run
,
nOffset
);
pt
.
y
+=
ME_GetParagraph
(
pRun
)
->
member
.
para
.
nYPos
;
pt
.
y
+=
ME_GetParagraph
(
pRun
)
->
member
.
para
.
pt
.
y
;
}
else
{
pt
.
x
=
0
;
pt
.
y
=
editor
->
pBuffer
->
pLast
->
member
.
para
.
nYPos
;
pt
.
y
=
editor
->
pBuffer
->
pLast
->
member
.
para
.
pt
.
y
;
}
pt
.
x
+=
editor
->
selofs
;
...
...
@@ -3287,8 +3460,13 @@ static LRESULT RichEditWndProc_common(HWND hWnd, UINT msg, WPARAM wParam,
||
(
wstr
==
'\r'
&&
(
GetWindowLongW
(
hWnd
,
GWL_STYLE
)
&
ES_MULTILINE
))
||
wstr
==
'\t'
)
{
int
from
,
to
;
BOOL
ctrl_is_down
=
GetKeyState
(
VK_CONTROL
)
&
0x8000
;
ME_GetSelection
(
editor
,
&
from
,
&
to
);
if
(
wstr
==
'\t'
)
{
if
(
wstr
==
'\t'
/* v4.1 allows tabs to be inserted with ctrl key down */
&&
!
(
ctrl_is_down
&&
!
editor
->
bEmulateVersion10
)
)
{
ME_Cursor
cursor
=
editor
->
pCursors
[
0
];
ME_DisplayItem
*
para
;
BOOL
bSelectedRow
=
FALSE
;
...
...
@@ -3726,7 +3904,12 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
if
(
nLen
>
nChars
)
nLen
=
nChars
;
if
(
item
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
if
(
item
->
member
.
run
.
nFlags
&
MERF_ENDCELL
&&
item
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
{
*
buffer
=
'\t'
;
}
else
if
(
item
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
{
if
(
!
ME_FindItemFwd
(
item
,
diRun
))
/* No '\r' is appended to the last paragraph. */
...
...
@@ -3738,10 +3921,16 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int nStart, int nChars, in
if
(
bCRLF
)
{
/* richedit 2.0 case - actual line-break is \r but should report \r\n */
assert
(
nLen
==
1
);
if
(
ME_GetParagraph
(
item
)
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
))
assert
(
nLen
==
2
);
else
assert
(
nLen
==
1
);
*
buffer
++
=
'\r'
;
*
buffer
=
'\n'
;
/* Later updated by nLen==1 at the end of the loop */
nWritten
++
;
if
(
nLen
==
1
)
nWritten
++
;
else
buffer
--
;
}
else
{
...
...
dlls/riched20/editor.h
View file @
300db376
...
...
@@ -217,7 +217,7 @@ void ME_SendRequestResize(ME_TextEditor *editor, BOOL force);
ME_DisplayItem
*
ME_GetParagraph
(
ME_DisplayItem
*
run
);
void
ME_GetSelectionParas
(
ME_TextEditor
*
editor
,
ME_DisplayItem
**
para
,
ME_DisplayItem
**
para_end
);
void
ME_MakeFirstParagraph
(
ME_TextEditor
*
editor
);
ME_DisplayItem
*
ME_SplitParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
rp
,
ME_Style
*
style
,
int
numCR
,
int
numLF
);
ME_DisplayItem
*
ME_SplitParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
rp
,
ME_Style
*
style
,
int
numCR
,
int
numLF
,
int
paraFlags
);
ME_DisplayItem
*
ME_JoinParagraphs
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
tp
,
BOOL
keepFirstParaFormat
);
void
ME_DumpParaStyle
(
ME_Paragraph
*
s
);
...
...
@@ -287,6 +287,14 @@ void ME_UpdateSelectionLinkAttribute(ME_TextEditor *editor);
/* table.c */
BOOL
ME_IsInTable
(
ME_DisplayItem
*
pItem
);
ME_DisplayItem
*
ME_InsertTableRowStartFromCursor
(
ME_TextEditor
*
editor
);
ME_DisplayItem
*
ME_InsertTableRowStartAtParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
para
);
ME_DisplayItem
*
ME_InsertTableCellFromCursor
(
ME_TextEditor
*
editor
);
ME_DisplayItem
*
ME_InsertTableRowEndFromCursor
(
ME_TextEditor
*
editor
);
ME_DisplayItem
*
ME_GetTableRowEnd
(
ME_DisplayItem
*
para
);
ME_DisplayItem
*
ME_GetTableRowStart
(
ME_DisplayItem
*
para
);
void
ME_CheckTablesForCorruption
(
ME_TextEditor
*
editor
);
void
ME_ProtectPartialTableDeletion
(
ME_TextEditor
*
editor
,
int
nOfs
,
int
*
nChars
);
void
ME_TabPressedInTable
(
ME_TextEditor
*
editor
,
BOOL
bSelectedRow
);
...
...
dlls/riched20/editstr.h
View file @
300db376
...
...
@@ -67,26 +67,27 @@ typedef enum {
diInvalid
,
diTextStart
,
/* start of the text buffer */
diParagraph
,
/* paragraph start */
diCell
,
/* cell start */
diRun
,
/* run (sequence of chars with the same character format) */
diStartRow
,
/* start of the row (line of text on the screen) */
diTextEnd
,
/* end of the text buffer */
/********************* these below are meant for finding only *********************/
diStartRowOrParagraph
,
/*
5
*/
diStartRowOrParagraph
,
/*
7
*/
diStartRowOrParagraphOrEnd
,
diRunOrParagraph
,
diRunOrStartRow
,
diParagraphOrEnd
,
diRunOrParagraphOrEnd
,
/* 1
0
*/
diRunOrParagraphOrEnd
,
/* 1
2
*/
diUndoInsertRun
,
/* 1
1
*/
diUndoDeleteRun
,
/* 1
2
*/
diUndoJoinParagraphs
,
/* 1
3
*/
diUndoSplitParagraph
,
/* 1
4
*/
diUndoSetParagraphFormat
,
/* 1
5
*/
diUndoSetCharFormat
,
/* 1
6
*/
diUndoEndTransaction
,
/* 1
7
- marks the end of a group of changes for undo */
diUndoPotentialEndTransaction
,
/*
18
- allows grouping typed chars for undo */
diUndoInsertRun
,
/* 1
3
*/
diUndoDeleteRun
,
/* 1
4
*/
diUndoJoinParagraphs
,
/* 1
5
*/
diUndoSplitParagraph
,
/* 1
6
*/
diUndoSetParagraphFormat
,
/* 1
7
*/
diUndoSetCharFormat
,
/* 1
8
*/
diUndoEndTransaction
,
/* 1
9
- marks the end of a group of changes for undo */
diUndoPotentialEndTransaction
,
/*
20
- allows grouping typed chars for undo */
}
ME_DIType
;
#define SELECTIONBAR_WIDTH 9
...
...
@@ -97,8 +98,10 @@ typedef enum {
#define MERF_GRAPHICS 0x001
/* run is a tab (or, in future, any kind of content whose size is dependent on run position) */
#define MERF_TAB 0x002
/* run is a cell boundary */
#define MERF_ENDCELL 0x004
/* v4.1 */
#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB)
#define MERF_NONTEXT (MERF_GRAPHICS | MERF_TAB
| MERF_ENDCELL
)
/* run is splittable (contains white spaces in the middle or end) */
#define MERF_SPLITTABLE 0x001000
...
...
@@ -118,6 +121,8 @@ typedef enum {
#define MERF_ENDROW 0x200000
/* run is hidden */
#define MERF_HIDDEN 0x400000
/* start of a table row has an empty paragraph that should be skipped over. */
#define MERF_TABLESTART 0x800000
/* v4.1 */
/* runs with any of these flags set cannot be joined */
#define MERF_NOJOIN (MERF_GRAPHICS|MERF_TAB|MERF_ENDPARA|MERF_ENDROW)
...
...
@@ -130,8 +135,12 @@ typedef enum {
/******************************** para flags *************************/
/* this paragraph was already wrapped and hasn't changed, every change resets that flag */
#define MEPF_REWRAP 1
#define MEPF_REPAINT 2
#define MEPF_REWRAP 0x01
#define MEPF_REPAINT 0x02
/* v4.1 */
#define MEPF_CELL 0x04
/* The paragraph is nested in a cell */
#define MEPF_ROWSTART 0x08
/* Hidden empty paragraph at the start of the row */
#define MEPF_ROWEND 0x10
/* Visible empty paragraph at the end of the row */
/******************************** structures *************************/
...
...
@@ -160,14 +169,26 @@ typedef struct tagME_Paragraph
{
PARAFORMAT2
*
pFmt
;
struct
tagME_DisplayItem
*
pCell
;
/* v4.1 */
int
nCharOfs
;
int
nFlags
;
int
nYPos
,
nHeight
;
POINT
pt
;
int
nHeight
;
int
nLastPaintYPos
,
nLastPaintHeight
;
int
nRows
;
struct
tagME_DisplayItem
*
prev_para
,
*
next_para
,
*
document
;
}
ME_Paragraph
;
typedef
struct
tagME_Cell
/* v4.1 */
{
int
nNestingLevel
;
/* 0 for normal cells, and greater for nested cells */
int
nRightBoundary
;
POINT
pt
;
int
nHeight
,
nWidth
;
struct
tagME_DisplayItem
*
prev_cell
,
*
next_cell
,
*
parent_cell
;
}
ME_Cell
;
typedef
struct
tagME_Row
{
int
nHeight
;
...
...
@@ -175,7 +196,7 @@ typedef struct tagME_Row
int
nWidth
;
int
nLMargin
;
int
nRMargin
;
int
nYPos
;
POINT
pt
;
}
ME_Row
;
/* the display item list layout is like this:
...
...
@@ -197,6 +218,7 @@ typedef struct tagME_DisplayItem
union
{
ME_Run
run
;
ME_Row
row
;
ME_Cell
cell
;
ME_Paragraph
para
;
ME_Document
doc
;
/* not used */
ME_Style
*
ustyle
;
/* used by diUndoSetCharFormat */
...
...
@@ -270,6 +292,9 @@ typedef struct tagME_OutStream {
COLORREF
colortbl
[
STREAMOUT_COLORTBL_SIZE
];
UINT
nDefaultFont
;
UINT
nDefaultCodePage
;
/* nNestingLevel = 0 means we aren't in a cell, 1 means we are in a cell,
* an greater numbers mean we are in a cell nested within a cell. */
UINT
nNestingLevel
;
}
ME_OutStream
;
typedef
struct
tagME_FontCacheItem
...
...
dlls/riched20/list.c
View file @
300db376
...
...
@@ -121,8 +121,11 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item) {
if
(
item
->
type
==
diUndoSetCharFormat
)
{
ME_ReleaseStyle
(
item
->
member
.
ustyle
);
}
if
(
item
->
type
==
diUndoSplitParagraph
)
if
(
item
->
type
==
diUndoSplitParagraph
)
{
FREE_OBJ
(
item
->
member
.
para
.
pFmt
);
if
(
item
->
member
.
para
.
pCell
)
FREE_OBJ
(
item
->
member
.
para
.
pCell
);
}
FREE_OBJ
(
item
);
}
...
...
@@ -146,6 +149,7 @@ const char *ME_GetDITypeName(ME_DIType type)
{
case
diParagraph
:
return
"diParagraph"
;
case
diRun
:
return
"diRun"
;
case
diCell
:
return
"diCell"
;
case
diTextStart
:
return
"diTextStart"
;
case
diTextEnd
:
return
"diTextEnd"
;
case
diStartRow
:
return
"diStartRow"
;
...
...
@@ -172,8 +176,17 @@ void ME_DumpDocument(ME_TextBuffer *buffer)
case
diTextStart
:
TRACE
(
"Start
\n
"
);
break
;
case
diCell
:
TRACE
(
"Cell(level=%d%s)
\n
"
,
pItem
->
member
.
cell
.
nNestingLevel
,
!
pItem
->
member
.
cell
.
next_cell
?
", END"
:
(
!
pItem
->
member
.
cell
.
prev_cell
?
", START"
:
""
));
break
;
case
diParagraph
:
TRACE
(
"Paragraph(ofs=%d)
\n
"
,
pItem
->
member
.
para
.
nCharOfs
);
if
(
pItem
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
TRACE
(
" - (Table Row Start)
\n
"
);
if
(
pItem
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
TRACE
(
" - (Table Row End)
\n
"
);
break
;
case
diStartRow
:
TRACE
(
" - StartRow
\n
"
);
...
...
dlls/riched20/paint.c
View file @
300db376
...
...
@@ -32,13 +32,21 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
yoffset
=
ME_GetYScrollPos
(
editor
);
ME_InitContext
(
&
c
,
editor
,
hDC
);
SetBkMode
(
hDC
,
TRANSPARENT
);
ME_MoveCaret
(
editor
);
ME_MoveCaret
(
editor
);
/* Calls ME_WrapMarkedParagraphs */
item
=
editor
->
pBuffer
->
pFirst
->
next
;
c
.
pt
.
y
-=
yoffset
;
while
(
item
!=
editor
->
pBuffer
->
pLast
)
{
int
ye
;
assert
(
item
->
type
==
diParagraph
);
ye
=
c
.
pt
.
y
+
item
->
member
.
para
.
nHeight
;
if
(
item
->
member
.
para
.
pCell
!=
item
->
member
.
para
.
next_para
->
member
.
para
.
pCell
)
{
ME_Cell
*
cell
=
NULL
;
cell
=
&
ME_FindItemBack
(
item
->
member
.
para
.
next_para
,
diCell
)
->
member
.
cell
;
ye
=
cell
->
pt
.
y
+
cell
->
nHeight
-
yoffset
;
}
else
{
ye
=
c
.
pt
.
y
+
item
->
member
.
para
.
nHeight
;
}
if
(
!
bOnlyNew
||
(
item
->
member
.
para
.
nFlags
&
MEPF_REPAINT
))
{
BOOL
bPaint
=
(
rcUpdate
==
NULL
);
...
...
@@ -51,7 +59,31 @@ void ME_PaintContent(ME_TextEditor *editor, HDC hDC, BOOL bOnlyNew, const RECT *
item
->
member
.
para
.
nFlags
&=
~
MEPF_REPAINT
;
}
}
c
.
pt
.
y
=
ye
;
if
(
item
->
member
.
para
.
pCell
)
{
ME_Cell
*
cell
=
&
item
->
member
.
para
.
pCell
->
member
.
cell
;
c
.
pt
.
x
=
cell
->
pt
.
x
+
cell
->
nWidth
;
if
(
item
->
member
.
para
.
pCell
==
item
->
member
.
para
.
next_para
->
member
.
para
.
pCell
)
{
c
.
pt
.
y
=
ye
;
}
else
{
if
(
item
->
member
.
para
.
next_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
cell
=
&
ME_FindItemFwd
(
item
->
member
.
para
.
next_para
,
diCell
)
->
member
.
cell
;
}
else
if
(
item
->
member
.
para
.
next_para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
cell
=
&
cell
->
next_cell
->
member
.
cell
;
}
else
{
cell
=
&
item
->
member
.
para
.
next_para
->
member
.
para
.
pCell
->
member
.
cell
;
}
c
.
pt
.
y
=
cell
->
pt
.
y
-
yoffset
;
}
}
else
if
(
!
(
item
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
))
{
c
.
pt
.
y
=
ye
;
}
item
=
item
->
member
.
para
.
next_para
;
}
if
(
c
.
pt
.
y
<
c
.
rcView
.
bottom
)
{
...
...
@@ -394,19 +426,19 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
if
(
runofs
>=
nSelFrom
&&
runofs
<
nSelTo
)
{
ME_HighlightSpace
(
c
,
x
,
y
,
wszSpace
,
1
,
run
->
style
,
0
,
0
,
1
,
c
->
pt
.
y
+
start
->
member
.
row
.
nYPos
,
c
->
pt
.
y
+
start
->
member
.
row
.
pt
.
y
,
start
->
member
.
row
.
nHeight
);
}
return
;
}
if
(
run
->
nFlags
&
MERF_TAB
)
if
(
run
->
nFlags
&
(
MERF_TAB
|
MERF_ENDCELL
)
)
{
/* wszSpace is used instead of the tab character because otherwise
* an unwanted symbol can be inserted instead. */
ME_DrawTextWithStyle
(
c
,
x
,
y
,
wszSpace
,
1
,
run
->
style
,
run
->
nWidth
,
nSelFrom
-
runofs
,
nSelTo
-
runofs
,
c
->
pt
.
y
+
start
->
member
.
row
.
nYPos
,
c
->
pt
.
y
+
start
->
member
.
row
.
pt
.
y
,
start
->
member
.
row
.
nHeight
);
return
;
}
...
...
@@ -420,13 +452,13 @@ static void ME_DrawRun(ME_Context *c, int x, int y, ME_DisplayItem *rundi, ME_Pa
ME_String
*
szMasked
=
ME_MakeStringR
(
c
->
editor
->
cPasswordMask
,
ME_StrVLen
(
run
->
strText
));
ME_DrawTextWithStyle
(
c
,
x
,
y
,
szMasked
->
szData
,
ME_StrVLen
(
szMasked
),
run
->
style
,
run
->
nWidth
,
nSelFrom
-
runofs
,
nSelTo
-
runofs
,
c
->
pt
.
y
+
start
->
member
.
row
.
nYPos
,
start
->
member
.
row
.
nHeight
);
nSelFrom
-
runofs
,
nSelTo
-
runofs
,
c
->
pt
.
y
+
start
->
member
.
row
.
pt
.
y
,
start
->
member
.
row
.
nHeight
);
ME_DestroyString
(
szMasked
);
}
else
ME_DrawTextWithStyle
(
c
,
x
,
y
,
run
->
strText
->
szData
,
ME_StrVLen
(
run
->
strText
),
run
->
style
,
run
->
nWidth
,
nSelFrom
-
runofs
,
nSelTo
-
runofs
,
c
->
pt
.
y
+
start
->
member
.
row
.
nYPos
,
start
->
member
.
row
.
nHeight
);
nSelFrom
-
runofs
,
nSelTo
-
runofs
,
c
->
pt
.
y
+
start
->
member
.
row
.
pt
.
y
,
start
->
member
.
row
.
nHeight
);
}
}
...
...
@@ -635,23 +667,38 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
ME_DisplayItem
*
p
;
ME_Run
*
run
;
ME_Paragraph
*
para
=
NULL
;
RECT
rc
,
rc
Para
,
bounds
;
RECT
rc
,
rc
Text
,
bounds
;
int
y
=
c
->
pt
.
y
;
int
height
=
0
,
baseline
=
0
,
no
=
0
,
pno
=
0
;
int
xs
=
0
,
xe
=
0
;
BOOL
visible
=
FALSE
;
c
->
pt
.
x
=
c
->
rcView
.
left
;
rc
Para
.
left
=
c
->
rcView
.
left
;
rc
Para
.
right
=
c
->
rcView
.
right
;
rc
.
left
=
c
->
rcView
.
left
;
rc
.
right
=
c
->
rcView
.
right
;
for
(
p
=
paragraph
;
p
!=
paragraph
->
member
.
para
.
next_para
;
p
=
p
->
next
)
{
switch
(
p
->
type
)
{
case
diParagraph
:
para
=
&
p
->
member
.
para
;
assert
(
para
);
pno
=
0
;
xs
=
c
->
rcView
.
left
+
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxStartIndent
);
xe
=
c
->
rcView
.
right
-
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxRightIndent
);
if
(
para
->
pCell
)
{
ME_Cell
*
cell
=
&
para
->
pCell
->
member
.
cell
;
rc
.
left
=
cell
->
pt
.
x
;
rc
.
right
=
rc
.
left
+
cell
->
nWidth
;
rcText
.
left
=
cell
->
pt
.
x
+
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxStartIndent
);
rcText
.
right
=
cell
->
pt
.
x
+
cell
->
nWidth
-
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxRightIndent
);
}
if
(
para
->
nFlags
&
MEPF_ROWSTART
)
{
ME_Cell
*
cell
=
&
para
->
next_para
->
member
.
para
.
pCell
->
member
.
cell
;
rc
.
right
=
cell
->
pt
.
x
;
}
else
if
(
para
->
nFlags
&
MEPF_ROWEND
)
{
ME_Cell
*
cell
=
&
para
->
prev_para
->
member
.
para
.
pCell
->
member
.
cell
;
rc
.
left
=
cell
->
pt
.
x
+
cell
->
nWidth
;
}
rcText
.
left
=
rc
.
left
+
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxStartIndent
);
rcText
.
right
=
rc
.
right
-
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxRightIndent
);
ME_DrawParaDecoration
(
c
,
para
,
y
,
&
bounds
);
y
+=
bounds
.
top
;
break
;
...
...
@@ -659,22 +706,18 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
/* we should have seen a diParagraph before */
assert
(
para
);
y
+=
height
;
rc
Para
.
top
=
y
;
rcPara
.
bottom
=
y
+
p
->
member
.
row
.
nHeight
;
visible
=
RectVisible
(
c
->
hDC
,
&
rcPara
)
;
if
(
visible
)
{
/* left margin */
rc
.
left
=
c
->
rcView
.
left
+
bounds
.
left
;
rc
.
right
=
xs
;
rc
.
top
=
y
;
rc
.
top
=
y
;
if
(
para
->
nFlags
&
MEPF_ROWSTART
)
{
ME_Cell
*
cell
=
&
para
->
next_para
->
member
.
para
.
pCell
->
member
.
cell
;
rc
.
bottom
=
y
+
cell
->
nHeight
;
}
else
if
(
para
->
nFlags
&
MEPF_ROWEND
)
{
ME_Cell
*
cell
=
&
para
->
prev_para
->
member
.
para
.
pCell
->
member
.
cell
;
rc
.
bottom
=
y
+
cell
->
nHeight
;
}
else
{
rc
.
bottom
=
y
+
p
->
member
.
row
.
nHeight
;
FillRect
(
c
->
hDC
,
&
rc
,
c
->
editor
->
hbrBackground
);
/* right margin */
rc
.
left
=
xe
;
rc
.
right
=
c
->
rcView
.
right
-
bounds
.
right
;
FillRect
(
c
->
hDC
,
&
rc
,
c
->
editor
->
hbrBackground
);
rc
.
left
=
xs
;
rc
.
right
=
xe
;
}
visible
=
RectVisible
(
c
->
hDC
,
&
rc
);
if
(
visible
)
{
FillRect
(
c
->
hDC
,
&
rc
,
c
->
editor
->
hbrBackground
);
}
if
(
me_debug
)
...
...
@@ -690,7 +733,7 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
height
=
p
->
member
.
row
.
nHeight
;
baseline
=
p
->
member
.
row
.
nBaseline
;
if
(
!
pno
++
)
xe
+=
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxOffset
);
rcText
.
right
+=
ME_twips2pointsX
(
c
,
para
->
pFmt
->
dxOffset
);
break
;
case
diRun
:
assert
(
para
);
...
...
@@ -721,6 +764,18 @@ void ME_DrawParagraph(ME_Context *c, ME_DisplayItem *paragraph) {
}
/* c->pt.x += p->member.run.nWidth; */
break
;
case
diCell
:
/* Clear any space at the bottom of the cell after the text. */
if
(
para
->
nFlags
&
MEPF_ROWSTART
)
break
;
y
+=
height
;
rc
.
top
=
y
;
rc
.
bottom
=
p
->
member
.
cell
.
pt
.
y
+
p
->
member
.
cell
.
nHeight
-
ME_GetYScrollPos
(
c
->
editor
);
if
(
RectVisible
(
c
->
hDC
,
&
rc
))
{
FillRect
(
c
->
hDC
,
&
rc
,
c
->
editor
->
hbrBackground
);
}
default:
break
;
}
...
...
@@ -867,7 +922,7 @@ void ME_EnsureVisible(ME_TextEditor *editor, ME_DisplayItem *pRun)
assert
(
pRow
);
assert
(
pPara
);
y
=
pPara
->
member
.
para
.
nYPos
+
pRow
->
member
.
row
.
nYPos
;
y
=
pPara
->
member
.
para
.
pt
.
y
+
pRow
->
member
.
row
.
pt
.
y
;
yheight
=
pRow
->
member
.
row
.
nHeight
;
yold
=
ME_GetYScrollPos
(
editor
);
yrel
=
y
-
yold
;
...
...
dlls/riched20/para.c
View file @
300db376
...
...
@@ -104,17 +104,51 @@ void ME_MarkForPainting(ME_TextEditor *editor, ME_DisplayItem *first, const ME_D
}
}
static
void
ME_UpdateTableFlags
(
ME_DisplayItem
*
para
)
{
para
->
member
.
para
.
pFmt
->
dwMask
|=
PFM_TABLE
|
PFM_TABLEROWDELIMITER
;
if
(
para
->
member
.
para
.
pCell
)
{
para
->
member
.
para
.
nFlags
|=
MEPF_CELL
;
}
else
{
para
->
member
.
para
.
nFlags
&=
~
MEPF_CELL
;
}
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
para
->
member
.
para
.
pFmt
->
wEffects
|=
PFE_TABLEROWDELIMITER
;
}
else
{
para
->
member
.
para
.
pFmt
->
wEffects
&=
~
PFE_TABLEROWDELIMITER
;
}
if
(
para
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_CELL
|
MEPF_ROWEND
))
para
->
member
.
para
.
pFmt
->
wEffects
|=
PFE_TABLE
;
else
para
->
member
.
para
.
pFmt
->
wEffects
&=
~
PFE_TABLE
;
}
/* split paragraph at the beginning of the run */
ME_DisplayItem
*
ME_SplitParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
run
,
ME_Style
*
style
,
int
numCR
,
int
numLF
)
ME_DisplayItem
*
ME_SplitParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
run
,
ME_Style
*
style
,
int
numCR
,
int
numLF
,
int
paraFlags
)
{
ME_DisplayItem
*
next_para
=
NULL
;
ME_DisplayItem
*
run_para
=
NULL
;
ME_DisplayItem
*
new_para
=
ME_MakeDI
(
diParagraph
);
ME_DisplayItem
*
end_run
=
ME_MakeRun
(
style
,
ME_MakeString
(
wszParagraphSign
),
MERF_ENDPARA
)
;
ME_DisplayItem
*
end_run
;
ME_UndoItem
*
undo
=
NULL
;
int
ofs
;
ME_DisplayItem
*
pp
;
int
end_len
=
numCR
+
numLF
;
int
run_flags
=
MERF_ENDPARA
;
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
/* At most 1 of MEPF_CELL, MEPF_ROWSTART, or MEPF_ROWEND should be set. */
assert
(
!
(
paraFlags
&
~
(
MEPF_CELL
|
MEPF_ROWSTART
|
MEPF_ROWEND
)));
assert
(
!
(
paraFlags
&
(
paraFlags
-
1
)));
if
(
paraFlags
==
MEPF_CELL
)
run_flags
|=
MERF_ENDCELL
;
else
if
(
paraFlags
==
MEPF_ROWSTART
)
run_flags
|=
MERF_TABLESTART
|
MERF_HIDDEN
;
}
else
{
/* v1.0 - v3.0 */
assert
(
!
(
paraFlags
&
(
MEPF_CELL
|
MEPF_ROWSTART
|
MEPF_ROWEND
)));
}
end_run
=
ME_MakeRun
(
style
,
ME_MakeString
(
wszParagraphSign
),
run_flags
);
assert
(
run
->
type
==
diRun
);
...
...
@@ -139,11 +173,11 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME
}
new_para
->
member
.
para
.
nCharOfs
=
ME_GetParagraph
(
run
)
->
member
.
para
.
nCharOfs
+
ofs
;
new_para
->
member
.
para
.
nCharOfs
+=
end_len
;
new_para
->
member
.
para
.
nFlags
=
MEPF_REWRAP
;
/* FIXME copy flags (if applicable) */
new_para
->
member
.
para
.
nFlags
=
MEPF_REWRAP
;
/* FIXME initialize format style and call ME_SetParaFormat blah blah */
*
new_para
->
member
.
para
.
pFmt
=
*
run_para
->
member
.
para
.
pFmt
;
/* insert paragraph into paragraph double linked list */
new_para
->
member
.
para
.
prev_para
=
run_para
;
new_para
->
member
.
para
.
next_para
=
next_para
;
...
...
@@ -154,6 +188,44 @@ ME_DisplayItem *ME_SplitParagraph(ME_TextEditor *editor, ME_DisplayItem *run, ME
ME_InsertBefore
(
run
,
new_para
);
ME_InsertBefore
(
new_para
,
end_run
);
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
paraFlags
&
(
MEPF_ROWSTART
|
MEPF_CELL
))
{
ME_DisplayItem
*
cell
=
ME_MakeDI
(
diCell
);
ME_InsertBefore
(
new_para
,
cell
);
new_para
->
member
.
para
.
pCell
=
cell
;
cell
->
member
.
cell
.
next_cell
=
NULL
;
if
(
paraFlags
&
MEPF_ROWSTART
)
{
run_para
->
member
.
para
.
nFlags
|=
MEPF_ROWSTART
;
cell
->
member
.
cell
.
prev_cell
=
NULL
;
cell
->
member
.
cell
.
parent_cell
=
run_para
->
member
.
para
.
pCell
;
if
(
run_para
->
member
.
para
.
pCell
)
cell
->
member
.
cell
.
nNestingLevel
=
run_para
->
member
.
para
.
pCell
->
member
.
cell
.
nNestingLevel
+
1
;
else
cell
->
member
.
cell
.
nNestingLevel
=
1
;
}
else
{
cell
->
member
.
cell
.
prev_cell
=
run_para
->
member
.
para
.
pCell
;
assert
(
cell
->
member
.
cell
.
prev_cell
);
cell
->
member
.
cell
.
prev_cell
->
member
.
cell
.
next_cell
=
cell
;
assert
(
run_para
->
member
.
para
.
nFlags
&
MEPF_CELL
);
assert
(
!
(
run_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
));
cell
->
member
.
cell
.
nNestingLevel
=
cell
->
member
.
cell
.
prev_cell
->
member
.
cell
.
nNestingLevel
;
cell
->
member
.
cell
.
parent_cell
=
cell
->
member
.
cell
.
prev_cell
->
member
.
cell
.
parent_cell
;
}
}
else
if
(
paraFlags
&
MEPF_ROWEND
)
{
run_para
->
member
.
para
.
nFlags
|=
MEPF_ROWEND
;
run_para
->
member
.
para
.
pCell
=
run_para
->
member
.
para
.
pCell
->
member
.
cell
.
parent_cell
;
new_para
->
member
.
para
.
pCell
=
run_para
->
member
.
para
.
pCell
;
assert
(
run_para
->
member
.
para
.
prev_para
->
member
.
para
.
nFlags
&
MEPF_CELL
);
assert
(
!
(
run_para
->
member
.
para
.
prev_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
));
}
else
{
new_para
->
member
.
para
.
pCell
=
run_para
->
member
.
para
.
pCell
;
}
ME_UpdateTableFlags
(
run_para
);
ME_UpdateTableFlags
(
new_para
);
}
/* force rewrap of the */
run_para
->
member
.
para
.
prev_para
->
member
.
para
.
nFlags
|=
MEPF_REWRAP
;
new_para
->
member
.
para
.
prev_para
->
member
.
para
.
nFlags
|=
MEPF_REWRAP
;
...
...
@@ -208,6 +280,42 @@ ME_DisplayItem *ME_JoinParagraphs(ME_TextEditor *editor, ME_DisplayItem *tp,
ME_AddUndoItem
(
editor
,
diUndoSetParagraphFormat
,
tp
);
*
tp
->
member
.
para
.
pFmt
=
*
pNext
->
member
.
para
.
pFmt
;
}
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
/* Table cell/row properties are always moved over from the removed para. */
tp
->
member
.
para
.
nFlags
=
pNext
->
member
.
para
.
nFlags
;
tp
->
member
.
para
.
pCell
=
pNext
->
member
.
para
.
pCell
;
/* Remove cell boundary if it is between the end paragraph run and the next
* paragraph display item. */
pTmp
=
pRun
->
next
;
while
(
pTmp
!=
pNext
)
{
if
(
pTmp
->
type
==
diCell
)
{
ME_Cell
*
pCell
=
&
pTmp
->
member
.
cell
;
if
(
undo
)
{
assert
(
!
(
undo
->
di
.
member
.
para
.
nFlags
&
MEPF_ROWEND
));
if
(
!
(
undo
->
di
.
member
.
para
.
nFlags
&
MEPF_ROWSTART
))
undo
->
di
.
member
.
para
.
nFlags
|=
MEPF_CELL
;
undo
->
di
.
member
.
para
.
pCell
=
ALLOC_OBJ
(
ME_DisplayItem
);
*
undo
->
di
.
member
.
para
.
pCell
=
*
pTmp
;
undo
->
di
.
member
.
para
.
pCell
->
next
=
NULL
;
undo
->
di
.
member
.
para
.
pCell
->
prev
=
NULL
;
undo
->
di
.
member
.
para
.
pCell
->
member
.
cell
.
next_cell
=
NULL
;
undo
->
di
.
member
.
para
.
pCell
->
member
.
cell
.
prev_cell
=
NULL
;
}
ME_Remove
(
pTmp
);
if
(
pCell
->
prev_cell
)
pCell
->
prev_cell
->
member
.
cell
.
next_cell
=
pCell
->
next_cell
;
if
(
pCell
->
next_cell
)
pCell
->
next_cell
->
member
.
cell
.
prev_cell
=
pCell
->
prev_cell
;
ME_DestroyDisplayItem
(
pTmp
);
break
;
}
pTmp
=
pTmp
->
next
;
}
}
shift
=
pNext
->
member
.
para
.
nCharOfs
-
tp
->
member
.
para
.
nCharOfs
-
end_len
;
...
...
dlls/riched20/rtf.h
View file @
300db376
...
...
@@ -1012,7 +1012,15 @@ struct RTFTable
{
RTFCell
cells
[
MAX_TABLE_CELLS
];
int
numCellsDefined
;
/* Used in v1.0 - v3.0 */
int
numCellsInserted
;
/* v4.1 */
/* tableRowStart may be the start row paragraph of the table row,
* or it may store the end of the previous row if it may still be
* continued, otherwise NULL is stored. */
ME_DisplayItem
*
tableRowStart
;
};
/*
...
...
dlls/riched20/run.c
View file @
300db376
...
...
@@ -134,6 +134,9 @@ void ME_CheckCharOffsets(ME_TextEditor *editor)
else
ofs
+=
ME_StrLen
(
p
->
member
.
run
.
strText
);
break
;
case
diCell
:
TRACE_
(
richedit_check
)(
"cell
\n
"
);
break
;
default:
assert
(
0
);
}
...
...
@@ -436,7 +439,7 @@ void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run)
{
assert
(
run
->
nCharOfs
!=
-
1
);
if
(
RUN_IS_HIDDEN
(
run
))
if
(
RUN_IS_HIDDEN
(
run
)
||
run
->
nFlags
&
MERF_TABLESTART
)
run
->
nFlags
|=
MERF_HIDDEN
;
else
run
->
nFlags
&=
~
MERF_HIDDEN
;
...
...
@@ -483,7 +486,8 @@ int ME_CharFromPoint(ME_Context *c, int cx, ME_Run *run)
if
(
!
run
->
strText
->
nLen
)
return
0
;
if
(
run
->
nFlags
&
MERF_TAB
)
if
(
run
->
nFlags
&
MERF_TAB
||
(
run
->
nFlags
&
(
MERF_ENDCELL
|
MERF_ENDPARA
))
==
MERF_ENDCELL
)
{
if
(
cx
<
run
->
nWidth
/
2
)
return
0
;
...
...
@@ -540,7 +544,7 @@ int ME_CharFromPointCursor(ME_TextEditor *editor, int cx, ME_Run *run)
if
(
!
run
->
strText
->
nLen
)
return
0
;
if
(
run
->
nFlags
&
MERF_TAB
)
if
(
run
->
nFlags
&
(
MERF_TAB
|
MERF_ENDCELL
)
)
{
if
(
cx
<
run
->
nWidth
/
2
)
return
0
;
...
...
dlls/riched20/table.c
View file @
300db376
...
...
@@ -21,18 +21,236 @@
/*
* The implementation of tables differs greatly between version 3.0
* (in riched20.dll) and version 4.1 (in msftedit.dll) of richedit controls.
* Currently Wine is not implementing table support as done in version 4.1.
* Currently Wine is not distinguishing between version 3.0 and version 4.1,
* so v4.1 is assumed unless v1.0 is being emulated (i.e. riched32.dll is used).
* If this lack of distinction causes a bug in a Windows application, then Wine
* will need to start making this distinction.
*
* Richedit version 1.0 - 3.0:
* Tables are implemented in these versions using tabs at the end of cells,
* and tab stops to position the cells. The paragraph format flag PFE_TABLE
* will indicate the the paragraph is a table row. Note that in this
* implementation there is one paragraph per table row.
*
* Richedit version 4.1:
* Tables are implemented such that cells can contain multiple paragraphs,
* each with it's own paragraph format, and cells may even contain tables
* nested within the cell.
*
* There are is also a paragraph at the start of each table row that contains
* the rows paragraph format (e.g. to change the row alignment to row), and a
* paragraph at the end of the table row with the PFE_TABLEROWDELIMITER flag
* set. The paragraphs at the start and end of the table row should always be
* empty, but should have a length of 2.
*
* Wine implements this using display items (ME_DisplayItem) with a type of
* diCell. These cell display items store the cell properties, and are
* inserted into the editors linked list before each cell, and at the end of
* the last cell. The cell display item for a cell comes before the paragraphs
* for the cell, but the last cell display item refers to no cell, so it is
* just a delimiter.
*/
#include "editor.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
richedit
);
WINE_DECLARE_DEBUG_CHANNEL
(
richedit_lists
);
static
ME_DisplayItem
*
ME_InsertEndParaFromCursor
(
ME_TextEditor
*
editor
,
int
nCursor
,
int
numCR
,
int
numLF
,
int
paraFlags
)
{
ME_Style
*
pStyle
=
ME_GetInsertStyle
(
editor
,
nCursor
);
ME_DisplayItem
*
tp
;
ME_Cursor
*
cursor
=
&
editor
->
pCursors
[
nCursor
];
if
(
cursor
->
nOffset
)
{
ME_SplitRunSimple
(
editor
,
cursor
->
pRun
,
cursor
->
nOffset
);
cursor
=
&
editor
->
pCursors
[
nCursor
];
}
tp
=
ME_SplitParagraph
(
editor
,
cursor
->
pRun
,
pStyle
,
numCR
,
numLF
,
paraFlags
);
cursor
->
pRun
=
ME_FindItemFwd
(
tp
,
diRun
);
return
tp
;
}
ME_DisplayItem
*
ME_InsertTableRowStartFromCursor
(
ME_TextEditor
*
editor
)
{
ME_DisplayItem
*
para
;
para
=
ME_InsertEndParaFromCursor
(
editor
,
0
,
1
,
1
,
MEPF_ROWSTART
);
return
para
->
member
.
para
.
prev_para
;
}
ME_DisplayItem
*
ME_InsertTableRowStartAtParagraph
(
ME_TextEditor
*
editor
,
ME_DisplayItem
*
para
)
{
ME_DisplayItem
*
prev_para
,
*
end_para
;
ME_Cursor
savedCursor
=
editor
->
pCursors
[
0
];
ME_DisplayItem
*
startRowPara
;
editor
->
pCursors
[
0
].
pRun
=
ME_FindItemFwd
(
para
,
diRun
);
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
startRowPara
=
ME_InsertTableRowStartFromCursor
(
editor
);
editor
->
pCursors
[
0
]
=
savedCursor
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
end_para
=
ME_GetParagraph
(
editor
->
pCursors
[
0
].
pRun
)
->
member
.
para
.
next_para
;
prev_para
=
startRowPara
->
member
.
para
.
next_para
;
para
=
prev_para
->
member
.
para
.
next_para
;
while
(
para
!=
end_para
)
{
para
->
member
.
para
.
pCell
=
prev_para
->
member
.
para
.
pCell
;
para
->
member
.
para
.
nFlags
|=
MEPF_CELL
;
para
->
member
.
para
.
nFlags
&=
~
(
MEPF_ROWSTART
|
MEPF_ROWEND
);
para
->
member
.
para
.
pFmt
->
dwMask
|=
PFM_TABLE
|
PFM_TABLEROWDELIMITER
;
para
->
member
.
para
.
pFmt
->
wEffects
|=
PFE_TABLE
;
para
->
member
.
para
.
pFmt
->
wEffects
&=
~
PFE_TABLEROWDELIMITER
;
prev_para
=
para
;
para
=
para
->
member
.
para
.
next_para
;
}
return
startRowPara
;
}
/* Inserts a diCell and starts a new paragraph for the next cell.
*
* Returns the first paragraph of the new cell. */
ME_DisplayItem
*
ME_InsertTableCellFromCursor
(
ME_TextEditor
*
editor
)
{
ME_DisplayItem
*
para
;
para
=
ME_InsertEndParaFromCursor
(
editor
,
0
,
1
,
0
,
MEPF_CELL
);
return
para
;
}
ME_DisplayItem
*
ME_InsertTableRowEndFromCursor
(
ME_TextEditor
*
editor
)
{
ME_DisplayItem
*
para
;
para
=
ME_InsertEndParaFromCursor
(
editor
,
0
,
1
,
1
,
MEPF_ROWEND
);
return
para
->
member
.
para
.
prev_para
;
}
ME_DisplayItem
*
ME_GetTableRowEnd
(
ME_DisplayItem
*
para
)
{
ME_DisplayItem
*
cell
;
assert
(
para
);
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
return
para
;
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
para
=
para
->
member
.
para
.
next_para
;
cell
=
para
->
member
.
para
.
pCell
;
assert
(
cell
&&
cell
->
type
==
diCell
);
while
(
cell
->
member
.
cell
.
next_cell
)
cell
=
cell
->
member
.
cell
.
next_cell
;
para
=
ME_FindItemFwd
(
cell
,
diParagraph
);
assert
(
para
&&
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
);
return
para
;
}
ME_DisplayItem
*
ME_GetTableRowStart
(
ME_DisplayItem
*
para
)
{
ME_DisplayItem
*
cell
;
assert
(
para
);
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
return
para
;
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
para
=
para
->
member
.
para
.
prev_para
;
cell
=
para
->
member
.
para
.
pCell
;
assert
(
cell
&&
cell
->
type
==
diCell
);
while
(
cell
->
member
.
cell
.
prev_cell
)
cell
=
cell
->
member
.
cell
.
prev_cell
;
para
=
ME_FindItemBack
(
cell
,
diParagraph
);
assert
(
para
&&
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
);
return
para
;
}
/* Make a bunch of assertions to make sure tables haven't been corrupted.
*
* These invariants may not hold true in the middle of streaming in rich text
* or during an undo and redo of streaming in rich text. It should be safe to
* call this method after an event is processed.
*/
void
ME_CheckTablesForCorruption
(
ME_TextEditor
*
editor
)
{
if
(
TRACE_ON
(
richedit_lists
))
{
TRACE_
(
richedit_lists
)(
"---
\n
"
);
ME_DumpDocument
(
editor
->
pBuffer
);
}
#ifndef NDEBUG
{
ME_DisplayItem
*
p
,
*
pPrev
;
pPrev
=
editor
->
pBuffer
->
pFirst
;
p
=
pPrev
->
next
;
if
(
!
editor
->
bEmulateVersion10
)
/* v4.1 */
{
while
(
p
->
type
==
diParagraph
)
{
assert
(
p
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
);
assert
(
p
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLEROWDELIMITER
);
if
(
p
->
member
.
para
.
pCell
)
{
assert
(
p
->
member
.
para
.
nFlags
&
MEPF_CELL
);
assert
(
p
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
);
}
if
(
p
->
member
.
para
.
pCell
!=
pPrev
->
member
.
para
.
pCell
)
{
/* There must be a diCell in between the paragraphs if pCell changes. */
ME_DisplayItem
*
pCell
=
ME_FindItemBack
(
p
,
diCell
);
assert
(
pCell
);
assert
(
ME_FindItemBack
(
p
,
diRun
)
==
ME_FindItemBack
(
pCell
,
diRun
));
}
if
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
/* ROWEND must come after a cell. */
assert
(
pPrev
->
member
.
para
.
pCell
);
assert
(
p
->
member
.
para
.
pCell
==
pPrev
->
member
.
para
.
pCell
->
member
.
cell
.
parent_cell
);
assert
(
p
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLEROWDELIMITER
);
}
else
if
(
p
->
member
.
para
.
pCell
)
{
assert
(
!
(
p
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLEROWDELIMITER
));
assert
(
pPrev
->
member
.
para
.
pCell
||
pPrev
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
);
if
(
pPrev
->
member
.
para
.
pCell
&&
!
(
pPrev
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
))
{
assert
(
p
->
member
.
para
.
pCell
->
member
.
cell
.
parent_cell
==
pPrev
->
member
.
para
.
pCell
->
member
.
cell
.
parent_cell
);
if
(
pPrev
->
member
.
para
.
pCell
!=
p
->
member
.
para
.
pCell
)
assert
(
pPrev
->
member
.
para
.
pCell
==
p
->
member
.
para
.
pCell
->
member
.
cell
.
prev_cell
);
}
}
else
if
(
!
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
))
{
assert
(
!
(
p
->
member
.
para
.
pFmt
->
wEffects
&
(
PFE_TABLE
|
PFE_TABLEROWDELIMITER
)));
/* ROWSTART must be followed by a cell. */
assert
(
!
(
p
->
member
.
para
.
nFlags
&
MEPF_CELL
));
/* ROWSTART must be followed by a cell. */
assert
(
!
(
pPrev
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
));
}
pPrev
=
p
;
p
=
p
->
member
.
para
.
next_para
;
}
}
else
{
/* v1.0 - 3.0 */
while
(
p
->
type
==
diParagraph
)
{
assert
(
!
(
p
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
|
MEPF_CELL
)));
assert
(
p
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
);
assert
(
!
(
p
->
member
.
para
.
pFmt
->
wEffects
&
PFM_TABLEROWDELIMITER
));
assert
(
!
p
->
member
.
para
.
pCell
);
p
=
p
->
member
.
para
.
next_para
;
}
return
;
}
assert
(
p
->
type
==
diTextEnd
);
assert
(
!
pPrev
->
member
.
para
.
pCell
);
}
#endif
}
BOOL
ME_IsInTable
(
ME_DisplayItem
*
pItem
)
{
...
...
@@ -52,9 +270,6 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
{
ME_Cursor
c
,
c2
;
ME_DisplayItem
*
this_para
,
*
end_para
;
ME_DisplayItem
*
pRun
;
int
nCharsToBoundary
;
ME_CursorFromCharOfs
(
editor
,
nOfs
,
&
c
);
this_para
=
ME_GetParagraph
(
c
.
pRun
);
ME_CursorFromCharOfs
(
editor
,
nOfs
+
*
nChars
,
&
c2
);
...
...
@@ -72,54 +287,111 @@ void ME_ProtectPartialTableDeletion(ME_TextEditor *editor, int nOfs,int *nChars)
end_para
=
end_para
->
member
.
para
.
next_para
;
}
}
if
(
this_para
->
member
.
para
.
nCharOfs
!=
nOfs
&&
this_para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
this_para
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
pRun
=
c
.
pRun
;
/* Find the next tab or end paragraph to use as a delete boundary */
while
(
!
(
pRun
->
member
.
run
.
nFlags
&
(
MERF_TAB
|
MERF_ENDPARA
)))
pRun
=
ME_FindItemFwd
(
pRun
,
diRun
);
nCharsToBoundary
=
pRun
->
member
.
run
.
nCharOfs
-
c
.
pRun
->
member
.
run
.
nCharOfs
-
c
.
nOffset
;
*
nChars
=
min
(
*
nChars
,
nCharsToBoundary
);
}
else
if
(
end_para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
end_para
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
if
(
this_para
==
end_para
)
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
this_para
->
member
.
para
.
pCell
!=
end_para
->
member
.
para
.
pCell
||
((
this_para
->
member
.
para
.
nFlags
|
end_para
->
member
.
para
.
nFlags
)
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
)))
{
pRun
=
c2
.
pRun
;
/* Find the previous tab or end paragraph to use as a delete boundary */
while
(
pRun
&&
!
(
pRun
->
member
.
run
.
nFlags
&
(
MERF_TAB
|
MERF_ENDPARA
)))
pRun
=
ME_FindItemBack
(
pRun
,
diRun
);
if
(
pRun
&&
pRun
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
while
(
this_para
!=
end_para
)
{
/* We are in the first cell, and have gone back to the previous
* paragraph, so nothing needs to be protected. */
pRun
=
NULL
;
ME_DisplayItem
*
next_para
=
this_para
->
member
.
para
.
next_para
;
BOOL
bTruancateDeletion
=
FALSE
;
if
(
this_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
/* The following while loop assumes that next_para is MEPF_ROWSTART,
* so moving back one paragraph let's it be processed as the start
* of the row. */
next_para
=
this_para
;
this_para
=
this_para
->
member
.
para
.
prev_para
;
}
else
if
(
next_para
->
member
.
para
.
pCell
!=
this_para
->
member
.
para
.
pCell
||
this_para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
/* Start of the deletion from after the start of the table row. */
bTruancateDeletion
=
TRUE
;
}
while
(
!
bTruancateDeletion
&&
next_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
next_para
=
ME_GetTableRowEnd
(
next_para
)
->
member
.
para
.
next_para
;
if
(
next_para
->
member
.
para
.
nCharOfs
>
nOfs
+
*
nChars
)
{
/* End of deletion is not past the end of the table row. */
next_para
=
this_para
->
member
.
para
.
next_para
;
/* Delete the end paragraph preceding the table row if the
* preceding table row will be empty. */
if
(
this_para
->
member
.
para
.
nCharOfs
>=
nOfs
)
{
next_para
=
next_para
->
member
.
para
.
next_para
;
}
bTruancateDeletion
=
TRUE
;
}
else
{
this_para
=
next_para
->
member
.
para
.
prev_para
;
}
}
if
(
bTruancateDeletion
)
{
ME_Run
*
end_run
=
&
ME_FindItemBack
(
next_para
,
diRun
)
->
member
.
run
;
int
nCharsNew
=
(
next_para
->
member
.
para
.
nCharOfs
-
nOfs
-
end_run
->
nCR
-
end_run
->
nLF
);
nCharsNew
=
max
(
nCharsNew
,
0
);
assert
(
nCharsNew
<=
*
nChars
);
*
nChars
=
nCharsNew
;
break
;
}
this_para
=
next_para
;
}
}
else
{
/* The deletion starts from before the row, so don't join it with
* previous non-empty paragraphs. */
pRun
=
NULL
;
if
(
nOfs
>
this_para
->
member
.
para
.
nCharOfs
)
pRun
=
ME_FindItemBack
(
end_para
,
diRun
);
if
(
!
pRun
)
pRun
=
ME_FindItemFwd
(
end_para
,
diRun
);
}
if
(
pRun
)
}
else
{
/* v1.0 - 3.0 */
ME_DisplayItem
*
pRun
;
int
nCharsToBoundary
;
if
(
this_para
->
member
.
para
.
nCharOfs
!=
nOfs
&&
this_para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
this_para
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
pRun
=
c
.
pRun
;
/* Find the next tab or end paragraph to use as a delete boundary */
while
(
!
(
pRun
->
member
.
run
.
nFlags
&
(
MERF_TAB
|
MERF_ENDPARA
)))
pRun
=
ME_FindItemFwd
(
pRun
,
diRun
);
nCharsToBoundary
=
pRun
->
member
.
run
.
nCharOfs
-
c
.
pRun
->
member
.
run
.
nCharOfs
-
c
.
nOffset
;
*
nChars
=
min
(
*
nChars
,
nCharsToBoundary
);
}
else
if
(
end_para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
end_para
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
nCharsToBoundary
=
ME_GetParagraph
(
pRun
)
->
member
.
para
.
nCharOfs
+
pRun
->
member
.
run
.
nCharOfs
-
nOfs
;
if
(
nCharsToBoundary
>=
0
)
*
nChars
=
min
(
*
nChars
,
nCharsToBoundary
);
if
(
this_para
==
end_para
)
{
pRun
=
c2
.
pRun
;
/* Find the previous tab or end paragraph to use as a delete boundary */
while
(
pRun
&&
!
(
pRun
->
member
.
run
.
nFlags
&
(
MERF_TAB
|
MERF_ENDPARA
)))
pRun
=
ME_FindItemBack
(
pRun
,
diRun
);
if
(
pRun
&&
pRun
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
{
/* We are in the first cell, and have gone back to the previous
* paragraph, so nothing needs to be protected. */
pRun
=
NULL
;
}
}
else
{
/* The deletion starts from before the row, so don't join it with
* previous non-empty paragraphs. */
pRun
=
NULL
;
if
(
nOfs
>
this_para
->
member
.
para
.
nCharOfs
)
pRun
=
ME_FindItemBack
(
end_para
,
diRun
);
if
(
!
pRun
)
pRun
=
ME_FindItemFwd
(
end_para
,
diRun
);
}
if
(
pRun
)
{
nCharsToBoundary
=
ME_GetParagraph
(
pRun
)
->
member
.
para
.
nCharOfs
+
pRun
->
member
.
run
.
nCharOfs
-
nOfs
;
if
(
nCharsToBoundary
>=
0
)
*
nChars
=
min
(
*
nChars
,
nCharsToBoundary
);
}
}
if
(
*
nChars
<
0
)
nChars
=
0
;
}
if
(
*
nChars
<
0
)
nChars
=
0
;
}
static
ME_DisplayItem
*
ME_AppendTableRow
(
ME_TextEditor
*
editor
,
...
...
@@ -131,18 +403,42 @@ static ME_DisplayItem* ME_AppendTableRow(ME_TextEditor *editor,
int
i
;
assert
(
table_row
);
run
=
ME_FindItemBack
(
table_row
->
member
.
para
.
next_para
,
diRun
);
pFmt
=
table_row
->
member
.
para
.
pFmt
;
assert
(
pFmt
->
dwMask
&
PFM_TABLE
&&
pFmt
->
wEffects
&
PFE_TABLE
);
editor
->
pCursors
[
0
].
pRun
=
run
;
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
ME_InsertTextFromCursor
(
editor
,
0
,
&
endl
,
1
,
run
->
member
.
run
.
style
);
run
=
editor
->
pCursors
[
0
].
pRun
;
for
(
i
=
0
;
i
<
pFmt
->
cTabCount
;
i
++
)
{
ME_InsertTextFromCursor
(
editor
,
0
,
&
tab
,
1
,
run
->
member
.
run
.
style
);
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
ME_DisplayItem
*
insertedCell
,
*
para
,
*
cell
;
cell
=
ME_FindItemFwd
(
table_row
,
diCell
);
run
=
ME_GetTableRowEnd
(
table_row
)
->
member
.
para
.
next_para
;
run
=
ME_FindItemFwd
(
run
,
diRun
);
editor
->
pCursors
[
0
].
pRun
=
run
;
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
para
=
ME_InsertTableRowStartFromCursor
(
editor
);
insertedCell
=
ME_FindItemFwd
(
para
,
diCell
);
/* Copy cell properties */
insertedCell
->
member
.
cell
.
nRightBoundary
=
cell
->
member
.
cell
.
nRightBoundary
;
while
(
cell
->
member
.
cell
.
next_cell
)
{
cell
=
cell
->
member
.
cell
.
next_cell
;
para
=
ME_InsertTableCellFromCursor
(
editor
);
insertedCell
=
ME_FindItemBack
(
para
,
diCell
);
/* Copy cell properties */
insertedCell
->
member
.
cell
.
nRightBoundary
=
cell
->
member
.
cell
.
nRightBoundary
;
};
ME_InsertTableRowEndFromCursor
(
editor
);
/* return the table row start for the inserted paragraph */
return
ME_FindItemFwd
(
cell
,
diParagraph
)
->
member
.
para
.
next_para
;
}
else
{
/* v1.0 - 3.0 */
run
=
ME_FindItemBack
(
table_row
->
member
.
para
.
next_para
,
diRun
);
pFmt
=
table_row
->
member
.
para
.
pFmt
;
assert
(
pFmt
->
dwMask
&
PFM_TABLE
&&
pFmt
->
wEffects
&
PFE_TABLE
);
editor
->
pCursors
[
0
].
pRun
=
run
;
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
ME_InsertTextFromCursor
(
editor
,
0
,
&
endl
,
1
,
run
->
member
.
run
.
style
);
run
=
editor
->
pCursors
[
0
].
pRun
;
for
(
i
=
0
;
i
<
pFmt
->
cTabCount
;
i
++
)
{
ME_InsertTextFromCursor
(
editor
,
0
,
&
tab
,
1
,
run
->
member
.
run
.
style
);
}
return
table_row
->
member
.
para
.
next_para
;
}
return
table_row
->
member
.
para
.
next_para
;
}
/* Selects the next table cell or appends a new table row if at end of table */
...
...
@@ -154,43 +450,88 @@ static void ME_SelectOrInsertNextCell(ME_TextEditor *editor,
assert
(
run
&&
run
->
type
==
diRun
);
assert
(
ME_IsInTable
(
run
));
if
(
run
->
member
.
run
.
nFlags
&
MERF_ENDPARA
&&
ME_IsInTable
(
ME_FindItemFwd
(
run
,
diParagraphOrEnd
)))
{
run
=
ME_FindItemFwd
(
run
,
diRun
);
assert
(
run
);
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
while
(
!
(
run
->
member
.
run
.
nFlags
&
MERF_TAB
))
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
ME_DisplayItem
*
cell
;
/* Get the initial cell */
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
cell
=
para
->
member
.
para
.
next_para
->
member
.
para
.
pCell
;
}
else
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
cell
=
para
->
member
.
para
.
prev_para
->
member
.
para
.
pCell
;
}
else
{
cell
=
para
->
member
.
para
.
pCell
;
}
assert
(
cell
);
/* Get the next cell. */
if
(
cell
->
member
.
cell
.
next_cell
&&
cell
->
member
.
cell
.
next_cell
->
member
.
cell
.
next_cell
)
{
cell
=
cell
->
member
.
cell
.
next_cell
;
}
else
{
para
=
ME_GetTableRowEnd
(
ME_FindItemFwd
(
cell
,
diParagraph
));
para
=
para
->
member
.
para
.
next_para
;
assert
(
para
);
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
cell
=
para
->
member
.
para
.
next_para
->
member
.
para
.
pCell
;
}
else
{
/* Insert row */
para
=
para
->
member
.
para
.
prev_para
;
para
=
ME_AppendTableRow
(
editor
,
ME_GetTableRowStart
(
para
));
/* Put cursor at the start of the new table row */
para
=
para
->
member
.
para
.
next_para
;
editor
->
pCursors
[
0
].
pRun
=
ME_FindItemFwd
(
para
,
diRun
);
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
ME_WrapMarkedParagraphs
(
editor
);
return
;
}
}
/* Select cell */
editor
->
pCursors
[
1
].
pRun
=
ME_FindItemFwd
(
cell
,
diRun
);
editor
->
pCursors
[
1
].
nOffset
=
0
;
assert
(
editor
->
pCursors
[
0
].
pRun
);
cell
=
cell
->
member
.
cell
.
next_cell
;
editor
->
pCursors
[
0
].
pRun
=
ME_FindItemBack
(
cell
,
diRun
);
editor
->
pCursors
[
0
].
nOffset
=
0
;
assert
(
editor
->
pCursors
[
1
].
pRun
);
}
else
{
/* v1.0 - 3.0 */
if
(
run
->
member
.
run
.
nFlags
&
MERF_ENDPARA
&&
ME_IsInTable
(
ME_FindItemFwd
(
run
,
diParagraphOrEnd
)))
{
run
=
ME_FindItemFwd
(
run
,
diRunOrParagraphOrEnd
);
if
(
run
->
type
!=
diRun
)
run
=
ME_FindItemFwd
(
run
,
diRun
);
assert
(
run
);
}
for
(
i
=
0
;
i
<
2
;
i
++
)
{
while
(
!
(
run
->
member
.
run
.
nFlags
&
MERF_TAB
))
{
para
=
run
;
if
(
ME_IsInTable
(
para
)
)
run
=
ME_FindItemFwd
(
run
,
diRunOrParagraphOrEnd
)
;
if
(
run
->
type
!=
diRun
)
{
run
=
ME_FindItemFwd
(
para
,
diRun
);
assert
(
run
);
editor
->
pCursors
[
0
].
pRun
=
run
;
editor
->
pCursors
[
0
].
nOffset
=
0
;
i
=
1
;
}
else
{
/* Insert table row */
para
=
ME_AppendTableRow
(
editor
,
para
->
member
.
para
.
prev_para
);
/* Put cursor at the start of the new table row */
editor
->
pCursors
[
0
].
pRun
=
ME_FindItemFwd
(
para
,
diRun
);
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
ME_WrapMarkedParagraphs
(
editor
);
return
;
para
=
run
;
if
(
ME_IsInTable
(
para
))
{
run
=
ME_FindItemFwd
(
para
,
diRun
);
assert
(
run
);
editor
->
pCursors
[
0
].
pRun
=
run
;
editor
->
pCursors
[
0
].
nOffset
=
0
;
i
=
1
;
}
else
{
/* Insert table row */
para
=
ME_AppendTableRow
(
editor
,
para
->
member
.
para
.
prev_para
);
/* Put cursor at the start of the new table row */
editor
->
pCursors
[
0
].
pRun
=
ME_FindItemFwd
(
para
,
diRun
);
editor
->
pCursors
[
0
].
nOffset
=
0
;
editor
->
pCursors
[
1
]
=
editor
->
pCursors
[
0
];
ME_WrapMarkedParagraphs
(
editor
);
return
;
}
}
}
if
(
i
==
0
)
run
=
ME_FindItemFwd
(
run
,
diRun
);
editor
->
pCursors
[
i
].
pRun
=
run
;
editor
->
pCursors
[
i
].
nOffset
=
0
;
}
if
(
i
==
0
)
run
=
ME_FindItemFwd
(
run
,
diRun
);
editor
->
pCursors
[
i
].
pRun
=
run
;
editor
->
pCursors
[
i
].
nOffset
=
0
;
}
}
...
...
@@ -213,18 +554,25 @@ void ME_TabPressedInTable(ME_TextEditor *editor, BOOL bSelectedRow)
toCursor
=
editor
->
pCursors
[
0
];
}
}
if
(
!
ME_IsInTable
(
fromCursor
.
pRun
))
if
(
!
editor
->
bEmulateVersion10
)
/* v4.1 */
{
editor
->
pCursors
[
0
]
=
fromCursor
;
editor
->
pCursors
[
1
]
=
fromCursor
;
/* FIXME: For some reason the caret is shown at the start of the
* previous paragraph in v1.0 to v3.0, and bCaretAtEnd only works
* within the paragraph for wrapped lines. */
if
(
ME_FindItemBack
(
fromCursor
.
pRun
,
diRun
))
editor
->
bCaretAtEnd
=
TRUE
;
}
else
{
if
(
bSelectedRow
||
!
ME_IsInTable
(
toCursor
.
pRun
))
if
(
!
ME_IsInTable
(
toCursor
.
pRun
))
{
editor
->
pCursors
[
0
]
=
toCursor
;
editor
->
pCursors
[
1
]
=
toCursor
;
}
else
{
ME_SelectOrInsertNextCell
(
editor
,
toCursor
.
pRun
);
}
}
else
{
/* v1.0 - 3.0 */
if
(
!
ME_IsInTable
(
fromCursor
.
pRun
))
{
editor
->
pCursors
[
0
]
=
fromCursor
;
editor
->
pCursors
[
1
]
=
fromCursor
;
/* FIXME: For some reason the caret is shown at the start of the
* previous paragraph in v1.0 to v3.0, and bCaretAtEnd only works
* within the paragraph for wrapped lines. */
if
(
ME_FindItemBack
(
fromCursor
.
pRun
,
diRun
))
editor
->
bCaretAtEnd
=
TRUE
;
}
else
if
((
bSelectedRow
||
!
ME_IsInTable
(
toCursor
.
pRun
)))
{
ME_SelectOrInsertNextCell
(
editor
,
fromCursor
.
pRun
);
}
else
{
if
(
ME_IsSelection
(
editor
)
&&
!
toCursor
.
nOffset
)
...
...
dlls/riched20/undo.c
View file @
300db376
...
...
@@ -89,10 +89,17 @@ ME_UndoItem *ME_AddUndoItem(ME_TextEditor *editor, ME_DIType type, const ME_Disp
case
diUndoJoinParagraphs
:
break
;
case
diUndoSplitParagraph
:
{
ME_DisplayItem
*
prev_para
=
pdi
->
member
.
para
.
prev_para
;
assert
(
pdi
->
member
.
para
.
pFmt
->
cbSize
==
sizeof
(
PARAFORMAT2
));
pItem
->
member
.
para
.
pFmt
=
ALLOC_OBJ
(
PARAFORMAT2
);
pItem
->
member
.
para
.
pFmt
->
cbSize
=
sizeof
(
PARAFORMAT2
);
pItem
->
member
.
para
.
pFmt
->
dwMask
=
0
;
*
pItem
->
member
.
para
.
pFmt
=
*
pdi
->
member
.
para
.
pFmt
;
pItem
->
member
.
para
.
nFlags
=
prev_para
->
member
.
para
.
nFlags
&
~
MEPF_CELL
;
pItem
->
member
.
para
.
pCell
=
NULL
;
break
;
}
default:
assert
(
0
==
"AddUndoItem, unsupported item type"
);
return
NULL
;
...
...
@@ -314,16 +321,35 @@ static void ME_PlayUndoItem(ME_TextEditor *editor, ME_DisplayItem *pItem)
case
diUndoSplitParagraph
:
{
ME_Cursor
tmp
;
ME_DisplayItem
*
new_para
;
ME_DisplayItem
*
this_para
,
*
new_para
;
BOOL
bFixRowStart
;
int
paraFlags
=
pItem
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_CELL
|
MEPF_ROWEND
);
ME_CursorFromCharOfs
(
editor
,
pUItem
->
nStart
,
&
tmp
);
if
(
tmp
.
nOffset
)
tmp
.
pRun
=
ME_SplitRunSimple
(
editor
,
tmp
.
pRun
,
tmp
.
nOffset
);
assert
(
pUItem
->
nCR
>=
0
);
assert
(
pUItem
->
nLF
>=
0
);
this_para
=
ME_GetParagraph
(
tmp
.
pRun
);
bFixRowStart
=
this_para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
;
if
(
bFixRowStart
)
{
/* Re-insert the paragraph before the table, making sure the nFlag value
* is correct. */
this_para
->
member
.
para
.
nFlags
&=
~
MEPF_ROWSTART
;
}
new_para
=
ME_SplitParagraph
(
editor
,
tmp
.
pRun
,
tmp
.
pRun
->
member
.
run
.
style
,
pUItem
->
nCR
,
pUItem
->
nLF
);
pUItem
->
nCR
,
pUItem
->
nLF
,
paraFlags
);
if
(
bFixRowStart
)
new_para
->
member
.
para
.
nFlags
|=
MEPF_ROWSTART
;
assert
(
pItem
->
member
.
para
.
pFmt
->
cbSize
==
sizeof
(
PARAFORMAT2
));
*
new_para
->
member
.
para
.
pFmt
=
*
pItem
->
member
.
para
.
pFmt
;
if
(
pItem
->
member
.
para
.
pCell
)
{
ME_DisplayItem
*
pItemCell
,
*
pCell
;
pItemCell
=
pItem
->
member
.
para
.
pCell
;
pCell
=
new_para
->
member
.
para
.
pCell
;
pCell
->
member
.
cell
.
nRightBoundary
=
pItemCell
->
member
.
cell
.
nRightBoundary
;
}
break
;
}
default:
...
...
@@ -361,6 +387,7 @@ BOOL ME_Undo(ME_TextEditor *editor) {
if
(
p
)
p
->
prev
=
NULL
;
ME_AddUndoItem
(
editor
,
diUndoEndTransaction
,
NULL
);
ME_CheckTablesForCorruption
(
editor
);
editor
->
nUndoStackSize
--
;
editor
->
nUndoMode
=
nMode
;
ME_UpdateRepaint
(
editor
);
...
...
@@ -396,6 +423,7 @@ BOOL ME_Redo(ME_TextEditor *editor) {
if
(
p
)
p
->
prev
=
NULL
;
ME_AddUndoItem
(
editor
,
diUndoEndTransaction
,
NULL
);
ME_CheckTablesForCorruption
(
editor
);
editor
->
nUndoMode
=
nMode
;
ME_UpdateRepaint
(
editor
);
return
TRUE
;
...
...
dlls/riched20/wrap.c
View file @
300db376
...
...
@@ -42,17 +42,37 @@ static ME_DisplayItem *ME_MakeRow(int height, int baseline, int width)
return
item
;
}
static
void
ME_BeginRow
(
ME_WrapContext
*
wc
)
static
void
ME_BeginRow
(
ME_WrapContext
*
wc
,
ME_DisplayItem
*
para
)
{
assert
(
para
&&
para
->
type
==
diParagraph
);
wc
->
pRowStart
=
NULL
;
wc
->
bOverflown
=
FALSE
;
wc
->
pLastSplittableRun
=
NULL
;
if
(
wc
->
context
->
editor
->
bWordWrap
)
wc
->
nAvailWidth
=
wc
->
context
->
rcView
.
right
-
wc
->
context
->
rcView
.
left
-
(
wc
->
nRow
?
wc
->
nLeftMargin
:
wc
->
nFirstMargin
)
-
wc
->
nRightMargin
;
else
if
(
para
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
))
{
wc
->
nAvailWidth
=
0
;
if
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
ME_Cell
*
cell
=
&
ME_FindItemBack
(
para
,
diCell
)
->
member
.
cell
;
cell
->
nWidth
=
0
;
}
}
else
if
(
para
->
member
.
para
.
pCell
)
{
ME_Cell
*
cell
=
&
para
->
member
.
para
.
pCell
->
member
.
cell
;
int
width
;
width
=
cell
->
nRightBoundary
;
if
(
cell
->
prev_cell
)
width
-=
cell
->
prev_cell
->
member
.
cell
.
nRightBoundary
;
cell
->
nWidth
=
max
(
ME_twips2pointsX
(
wc
->
context
,
width
),
0
);
wc
->
nAvailWidth
=
cell
->
nWidth
-
(
wc
->
nRow
?
wc
->
nLeftMargin
:
wc
->
nFirstMargin
)
-
wc
->
nRightMargin
;
}
else
if
(
wc
->
context
->
editor
->
bWordWrap
)
{
wc
->
nAvailWidth
=
wc
->
context
->
rcView
.
right
-
wc
->
context
->
rcView
.
left
-
(
wc
->
nRow
?
wc
->
nLeftMargin
:
wc
->
nFirstMargin
)
-
wc
->
nRightMargin
;
}
else
{
wc
->
nAvailWidth
=
~
0u
>>
1
;
wc
->
pt
.
x
=
0
;
}
wc
->
pt
.
x
=
wc
->
context
->
pt
.
x
;
}
static
void
ME_InsertRowStart
(
ME_WrapContext
*
wc
,
const
ME_DisplayItem
*
pEnd
)
...
...
@@ -100,7 +120,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
}
row
=
ME_MakeRow
(
ascent
+
descent
,
ascent
,
width
);
row
->
member
.
row
.
nYPos
=
wc
->
pt
.
y
;
row
->
member
.
row
.
pt
=
wc
->
pt
;
row
->
member
.
row
.
nLMargin
=
(
!
wc
->
nRow
?
wc
->
nFirstMargin
:
wc
->
nLeftMargin
);
row
->
member
.
row
.
nRMargin
=
wc
->
nRightMargin
;
assert
(
para
->
member
.
para
.
pFmt
->
dwMask
&
PFM_ALIGNMENT
);
...
...
@@ -118,7 +138,7 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
ME_InsertBefore
(
wc
->
pRowStart
,
row
);
wc
->
nRow
++
;
wc
->
pt
.
y
+=
ascent
+
descent
;
ME_BeginRow
(
wc
);
ME_BeginRow
(
wc
,
para
);
}
static
void
ME_WrapEndParagraph
(
ME_WrapContext
*
wc
,
ME_DisplayItem
*
p
)
...
...
@@ -326,9 +346,9 @@ static ME_DisplayItem *ME_WrapHandleRun(ME_WrapContext *wc, ME_DisplayItem *p)
}
/* will current run fit? */
if
(
wc
->
pt
.
x
+
run
->
nWidth
>
wc
->
nAvailWidth
)
if
(
wc
->
pt
.
x
+
run
->
nWidth
>
wc
->
context
->
pt
.
x
+
wc
->
nAvailWidth
)
{
int
loc
=
wc
->
nAvailWidth
-
wc
->
pt
.
x
;
int
loc
=
wc
->
context
->
pt
.
x
+
wc
->
nAvailWidth
-
wc
->
pt
.
x
;
/* total white run ? */
if
(
run
->
nFlags
&
MERF_WHITESPACE
)
{
/* let the overflow logic handle it */
...
...
@@ -421,7 +441,6 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD begino
wc
.
nLeftMargin
=
wc
.
nFirstMargin
+
ME_twips2pointsX
(
c
,
tp
->
member
.
para
.
pFmt
->
dxOffset
);
wc
.
nRightMargin
=
ME_twips2pointsX
(
c
,
tp
->
member
.
para
.
pFmt
->
dxRightIndent
);
wc
.
nRow
=
0
;
wc
.
pt
.
x
=
0
;
wc
.
pt
.
y
=
0
;
if
(
tp
->
member
.
para
.
pFmt
->
dwMask
&
PFM_SPACEBEFORE
)
wc
.
pt
.
y
+=
ME_twips2pointsY
(
c
,
tp
->
member
.
para
.
pFmt
->
dySpaceBefore
);
...
...
@@ -440,7 +459,7 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp, DWORD begino
linespace
=
ME_GetParaLineSpace
(
c
,
&
tp
->
member
.
para
);
ME_BeginRow
(
&
wc
);
ME_BeginRow
(
&
wc
,
tp
);
for
(
p
=
tp
->
next
;
p
!=
tp
->
member
.
para
.
next_para
;
)
{
assert
(
p
->
type
!=
diStartRow
);
if
(
p
->
type
==
diRun
)
{
...
...
@@ -515,11 +534,11 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
BOOL
bRedraw
=
FALSE
;
assert
(
item
->
type
==
diParagraph
);
editor
->
nHeight
=
max
(
editor
->
nHeight
,
item
->
member
.
para
.
nYPos
);
editor
->
nHeight
=
max
(
editor
->
nHeight
,
item
->
member
.
para
.
pt
.
y
);
if
((
item
->
member
.
para
.
nFlags
&
MEPF_REWRAP
)
||
(
item
->
member
.
para
.
nYPos
!=
c
.
pt
.
y
))
||
(
item
->
member
.
para
.
pt
.
y
!=
c
.
pt
.
y
))
bRedraw
=
TRUE
;
item
->
member
.
para
.
nYPos
=
c
.
pt
.
y
;
item
->
member
.
para
.
pt
=
c
.
pt
;
ME_WrapTextParagraph
(
&
c
,
item
,
editor
->
selofs
);
...
...
@@ -532,24 +551,90 @@ BOOL ME_WrapMarkedParagraphs(ME_TextEditor *editor) {
bModified
=
bModified
|
bRedraw
;
yLastPos
=
c
.
pt
.
y
;
c
.
pt
.
y
+=
item
->
member
.
para
.
nHeight
;
yLastPos
=
max
(
yLastPos
,
c
.
pt
.
y
);
if
(
item
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
ME_DisplayItem
*
cell
=
ME_FindItemFwd
(
item
,
diCell
);
cell
->
member
.
cell
.
pt
=
c
.
pt
;
}
else
if
(
item
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
/* Set all the cells to the height of the largest cell */
ME_DisplayItem
*
startRowPara
;
int
prevHeight
,
nHeight
;
ME_DisplayItem
*
cell
=
ME_FindItemBack
(
item
,
diCell
);
prevHeight
=
cell
->
member
.
cell
.
nHeight
;
nHeight
=
cell
->
member
.
cell
.
prev_cell
->
member
.
cell
.
nHeight
;
cell
->
member
.
cell
.
nHeight
=
nHeight
;
item
->
member
.
para
.
nHeight
=
nHeight
;
cell
=
cell
->
member
.
cell
.
prev_cell
;
while
(
cell
->
member
.
cell
.
prev_cell
)
{
cell
=
cell
->
member
.
cell
.
prev_cell
;
cell
->
member
.
cell
.
nHeight
=
nHeight
;
}
/* Also set the height of the start row paragraph */
startRowPara
=
ME_FindItemBack
(
cell
,
diParagraph
);
startRowPara
->
member
.
para
.
nHeight
=
nHeight
;
c
.
pt
.
x
=
startRowPara
->
member
.
para
.
pt
.
x
;
c
.
pt
.
y
=
cell
->
member
.
cell
.
pt
.
y
+
nHeight
;
if
(
prevHeight
<
nHeight
)
{
/* The height of the cells has grown, so invalidate the bottom of
* the cells. */
item
->
member
.
para
.
nFlags
|=
MEPF_REPAINT
;
cell
=
ME_FindItemBack
(
item
,
diCell
);
while
(
cell
)
{
ME_FindItemBack
(
cell
,
diParagraph
)
->
member
.
para
.
nFlags
|=
MEPF_REPAINT
;
cell
=
cell
->
member
.
cell
.
prev_cell
;
}
}
}
else
if
(
item
->
member
.
para
.
pCell
&&
item
->
member
.
para
.
pCell
!=
item
->
member
.
para
.
next_para
->
member
.
para
.
pCell
)
{
/* The next paragraph is in the next cell in the table row. */
ME_Cell
*
cell
=
&
item
->
member
.
para
.
pCell
->
member
.
cell
;
cell
->
nHeight
=
c
.
pt
.
y
+
item
->
member
.
para
.
nHeight
-
cell
->
pt
.
y
;
/* Propagate the largest height to the end so that it can be easily
* sent back to all the cells at the end of the row. */
if
(
cell
->
prev_cell
)
cell
->
nHeight
=
max
(
cell
->
nHeight
,
cell
->
prev_cell
->
member
.
cell
.
nHeight
);
c
.
pt
.
x
=
cell
->
pt
.
x
+
cell
->
nWidth
;
c
.
pt
.
y
=
cell
->
pt
.
y
;
cell
->
next_cell
->
member
.
cell
.
pt
=
c
.
pt
;
}
else
{
if
(
item
->
member
.
para
.
pCell
)
{
/* Next paragraph in the same cell. */
c
.
pt
.
x
=
item
->
member
.
para
.
pCell
->
member
.
cell
.
pt
.
x
;
}
else
{
/* Normal paragraph */
c
.
pt
.
x
=
0
;
}
c
.
pt
.
y
+=
item
->
member
.
para
.
nHeight
;
}
item
=
item
->
member
.
para
.
next_para
;
}
editor
->
sizeWindow
.
cx
=
c
.
rcView
.
right
-
c
.
rcView
.
left
;
editor
->
sizeWindow
.
cy
=
c
.
rcView
.
bottom
-
c
.
rcView
.
top
;
editor
->
nTotalLength
=
c
.
pt
.
y
;
editor
->
pBuffer
->
pLast
->
member
.
para
.
nYPos
=
yLastPos
;
editor
->
pBuffer
->
pLast
->
member
.
para
.
pt
.
x
=
0
;
editor
->
pBuffer
->
pLast
->
member
.
para
.
pt
.
y
=
yLastPos
;
ME_DestroyContext
(
&
c
,
editor
->
hWnd
);
/* Each paragraph may contain multiple rows, which should be scrollable, even
if the containing paragraph has
nYPos
== 0 */
if the containing paragraph has
pt.y
== 0 */
item
=
editor
->
pBuffer
->
pFirst
;
while
((
item
=
ME_FindItemFwd
(
item
,
diStartRow
))
!=
NULL
)
{
assert
(
item
->
type
==
diStartRow
);
editor
->
nHeight
=
max
(
editor
->
nHeight
,
item
->
member
.
row
.
nYPos
);
editor
->
nHeight
=
max
(
editor
->
nHeight
,
item
->
member
.
row
.
pt
.
y
);
}
if
(
bModified
||
editor
->
nTotalLength
<
editor
->
nLastTotalLength
)
...
...
@@ -569,8 +654,8 @@ void ME_InvalidateMarkedParagraphs(ME_TextEditor *editor) {
ME_DisplayItem
*
item
=
editor
->
pBuffer
->
pFirst
;
while
(
item
!=
editor
->
pBuffer
->
pLast
)
{
if
(
item
->
member
.
para
.
nFlags
&
MEPF_REPAINT
)
{
rc
.
top
=
item
->
member
.
para
.
nYPos
-
ofs
;
rc
.
bottom
=
item
->
member
.
para
.
nYPos
+
item
->
member
.
para
.
nHeight
-
ofs
;
rc
.
top
=
item
->
member
.
para
.
pt
.
y
-
ofs
;
rc
.
bottom
=
item
->
member
.
para
.
pt
.
y
+
item
->
member
.
para
.
nHeight
-
ofs
;
InvalidateRect
(
editor
->
hWnd
,
&
rc
,
TRUE
);
}
item
=
item
->
member
.
para
.
next_para
;
...
...
dlls/riched20/writer.c
View file @
300db376
...
...
@@ -41,6 +41,7 @@ ME_StreamOutInit(ME_TextEditor *editor, EDITSTREAM *stream)
pStream
->
written
=
0
;
pStream
->
nFontTblLen
=
0
;
pStream
->
nColorTblLen
=
1
;
pStream
->
nNestingLevel
=
0
;
return
pStream
;
}
...
...
@@ -284,28 +285,43 @@ ME_StreamOutRTFFontAndColorTbl(ME_OutStream *pStream, ME_DisplayItem *pFirstRun,
}
static
BOOL
ME_StreamOutRTFTableProps
(
ME_OutStream
*
pStream
,
const
ME_DisplayItem
*
para
)
ME_StreamOutRTFTableProps
(
ME_TextEditor
*
editor
,
ME_OutStream
*
pStream
,
const
ME_DisplayItem
*
para
)
{
PARAFORMAT2
*
pFmt
;
ME_DisplayItem
*
cell
;
char
props
[
STREAMOUT_BUFFER_SIZE
]
=
""
;
int
i
;
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
trowd"
))
return
FALSE
;
pFmt
=
para
->
member
.
para
.
pFmt
;
for
(
i
=
0
;
i
<
pFmt
->
cTabCount
;
i
++
)
{
sprintf
(
props
,
"
\\
cellx%d"
,
pFmt
->
rgxTabs
[
i
]
&
0x00FFFFFF
);
if
(
!
ME_StreamOutPrint
(
pStream
,
props
))
return
FALSE
;
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
assert
(
para
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
);
cell
=
para
->
member
.
para
.
next_para
->
member
.
para
.
pCell
;
assert
(
cell
);
do
{
sprintf
(
props
,
"
\\
cellx%d"
,
cell
->
member
.
cell
.
nRightBoundary
);
if
(
!
ME_StreamOutPrint
(
pStream
,
props
))
return
FALSE
;
cell
=
cell
->
member
.
cell
.
next_cell
;
}
while
(
cell
->
member
.
cell
.
next_cell
);
}
else
{
/* v1.0 - 3.0 */
PARAFORMAT2
*
pFmt
=
para
->
member
.
para
.
pFmt
;
int
i
;
assert
(
!
(
para
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
|
MEPF_CELL
)));
for
(
i
=
0
;
i
<
pFmt
->
cTabCount
;
i
++
)
{
sprintf
(
props
,
"
\\
cellx%d"
,
pFmt
->
rgxTabs
[
i
]
&
0x00FFFFFF
);
if
(
!
ME_StreamOutPrint
(
pStream
,
props
))
return
FALSE
;
}
}
props
[
0
]
=
'\0'
;
return
TRUE
;
}
static
BOOL
ME_StreamOutRTFParaProps
(
ME_OutStream
*
pStream
,
const
ME_DisplayItem
*
para
)
ME_StreamOutRTFParaProps
(
ME_TextEditor
*
editor
,
ME_OutStream
*
pStream
,
const
ME_DisplayItem
*
para
)
{
PARAFORMAT2
*
fmt
=
para
->
member
.
para
.
pFmt
;
char
props
[
STREAMOUT_BUFFER_SIZE
]
=
""
;
...
...
@@ -315,8 +331,13 @@ ME_StreamOutRTFParaProps(ME_OutStream *pStream, const ME_DisplayItem *para)
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
pard"
))
return
FALSE
;
if
(
fmt
->
dwMask
&
PFM_TABLE
&&
fmt
->
wEffects
&
PFE_TABLE
)
strcat
(
props
,
"
\\
intbl"
);
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
pStream
->
nNestingLevel
>
0
)
strcat
(
props
,
"
\\
intbl"
);
}
else
{
/* v1.0 - 3.0 */
if
(
fmt
->
dwMask
&
PFM_TABLE
&&
fmt
->
wEffects
&
PFE_TABLE
)
strcat
(
props
,
"
\\
intbl"
);
}
/* TODO: PFM_BORDER. M$ does not emit any keywords for these properties, and
* when streaming border keywords in, PFM_BORDER is set, but wBorder field is
...
...
@@ -683,7 +704,7 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
/* TODO: section formatting properties */
if
(
!
ME_StreamOutRTFParaProps
(
pStream
,
ME_GetParagraph
(
p
)))
if
(
!
ME_StreamOutRTFParaProps
(
editor
,
pStream
,
ME_GetParagraph
(
p
)))
return
FALSE
;
while
(
1
)
...
...
@@ -691,14 +712,28 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
switch
(
p
->
type
)
{
case
diParagraph
:
if
(
p
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
p
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
if
(
!
ME_StreamOutRTFTableProps
(
pStream
,
p
))
if
(
!
editor
->
bEmulateVersion10
)
{
/* v4.1 */
if
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWSTART
)
{
pStream
->
nNestingLevel
++
;
if
(
!
ME_StreamOutRTFTableProps
(
editor
,
pStream
,
p
))
return
FALSE
;
}
else
if
(
p
->
member
.
para
.
nFlags
&
MEPF_ROWEND
)
{
pStream
->
nNestingLevel
--
;
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
row
\r\n
"
))
return
FALSE
;
}
else
if
(
!
ME_StreamOutRTFParaProps
(
editor
,
pStream
,
p
))
{
return
FALSE
;
}
}
else
{
/* v1.0 - 3.0 */
if
(
p
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
p
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
if
(
!
ME_StreamOutRTFTableProps
(
editor
,
pStream
,
p
))
return
FALSE
;
}
if
(
!
ME_StreamOutRTFParaProps
(
editor
,
pStream
,
p
))
return
FALSE
;
}
if
(
!
ME_StreamOutRTFParaProps
(
pStream
,
p
))
return
FALSE
;
pPara
=
p
;
break
;
case
diRun
:
...
...
@@ -706,10 +741,13 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
break
;
TRACE
(
"flags %xh
\n
"
,
p
->
member
.
run
.
nFlags
);
/* TODO: emit embedded objects */
if
(
pPara
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
))
break
;
if
(
p
->
member
.
run
.
nFlags
&
MERF_GRAPHICS
)
{
FIXME
(
"embedded objects are not handled
\n
"
);
}
else
if
(
p
->
member
.
run
.
nFlags
&
MERF_TAB
)
{
if
(
pPara
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
if
(
editor
->
bEmulateVersion10
&&
/* v1.0 - 3.0 */
pPara
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
pPara
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
{
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
cell "
))
...
...
@@ -718,9 +756,14 @@ ME_StreamOutRTF(ME_TextEditor *editor, ME_OutStream *pStream, int nStart, int nC
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
tab "
))
return
FALSE
;
}
}
else
if
(
p
->
member
.
run
.
nFlags
&
MERF_ENDCELL
)
{
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
cell "
))
return
FALSE
;
nChars
--
;
}
else
if
(
p
->
member
.
run
.
nFlags
&
MERF_ENDPARA
)
{
if
(
pPara
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
pPara
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
)
if
(
pPara
->
member
.
para
.
pFmt
->
dwMask
&
PFM_TABLE
&&
pPara
->
member
.
para
.
pFmt
->
wEffects
&
PFE_TABLE
&&
!
(
pPara
->
member
.
para
.
nFlags
&
(
MEPF_ROWSTART
|
MEPF_ROWEND
|
MEPF_CELL
)))
{
if
(
!
ME_StreamOutPrint
(
pStream
,
"
\\
row
\r\n
"
))
return
FALSE
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment