mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 15:08:14 +00:00
[RICHED20]
* Sync with Wine 1.7.17. CORE-8080 svn path=/trunk/; revision=62982
This commit is contained in:
parent
e0a2fe4bd2
commit
8552a1297e
21 changed files with 661 additions and 183 deletions
|
@ -40,6 +40,6 @@ list(APPEND ADDITIONAL_SOURCE
|
||||||
add_library(riched20 SHARED ${SOURCE} ${ADDITIONAL_SOURCE})
|
add_library(riched20 SHARED ${SOURCE} ${ADDITIONAL_SOURCE})
|
||||||
set_module_type(riched20 win32dll)
|
set_module_type(riched20 win32dll)
|
||||||
target_link_libraries(riched20 wine uuid)
|
target_link_libraries(riched20 wine uuid)
|
||||||
add_importlibs(riched20 ole32 oleaut32 imm32 user32 gdi32 msvcrt kernel32 ntdll)
|
add_importlibs(riched20 ole32 oleaut32 usp10 imm32 user32 gdi32 msvcrt kernel32 ntdll)
|
||||||
add_pch(riched20 editor.h SOURCE)
|
add_pch(riched20 editor.h SOURCE)
|
||||||
add_cd_file(TARGET riched20 DESTINATION reactos/system32 FOR all)
|
add_cd_file(TARGET riched20 DESTINATION reactos/system32 FOR all)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
|
@ -55,7 +56,19 @@ int ME_GetSelectionOfs(ME_TextEditor *editor, int *from, int *to)
|
||||||
|
|
||||||
int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to)
|
int ME_GetSelection(ME_TextEditor *editor, ME_Cursor **from, ME_Cursor **to)
|
||||||
{
|
{
|
||||||
if (ME_GetCursorOfs(&editor->pCursors[0]) < ME_GetCursorOfs(&editor->pCursors[1]))
|
int from_ofs = ME_GetCursorOfs( &editor->pCursors[0] );
|
||||||
|
int to_ofs = ME_GetCursorOfs( &editor->pCursors[1] );
|
||||||
|
BOOL swap = (from_ofs > to_ofs);
|
||||||
|
|
||||||
|
if (from_ofs == to_ofs)
|
||||||
|
{
|
||||||
|
/* If cursor[0] is at the beginning of a run and cursor[1] at the end
|
||||||
|
of the prev run then we need to swap. */
|
||||||
|
if (editor->pCursors[0].nOffset < editor->pCursors[1].nOffset)
|
||||||
|
swap = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!swap)
|
||||||
{
|
{
|
||||||
*from = &editor->pCursors[0];
|
*from = &editor->pCursors[0];
|
||||||
*to = &editor->pCursors[1];
|
*to = &editor->pCursors[1];
|
||||||
|
@ -127,7 +140,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
||||||
ME_SetCursorToStart(editor, &editor->pCursors[1]);
|
ME_SetCursorToStart(editor, &editor->pCursors[1]);
|
||||||
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
||||||
ME_InvalidateSelection(editor);
|
ME_InvalidateSelection(editor);
|
||||||
ME_ClearTempStyle(editor);
|
|
||||||
return len + 1;
|
return len + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +162,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
||||||
editor->pCursors[1] = editor->pCursors[0];
|
editor->pCursors[1] = editor->pCursors[0];
|
||||||
ME_Repaint(editor);
|
ME_Repaint(editor);
|
||||||
}
|
}
|
||||||
ME_ClearTempStyle(editor);
|
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,7 +190,6 @@ int ME_SetSelection(ME_TextEditor *editor, int from, int to)
|
||||||
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
ME_SetCursorToEnd(editor, &editor->pCursors[0]);
|
||||||
editor->pCursors[1] = editor->pCursors[0];
|
editor->pCursors[1] = editor->pCursors[0];
|
||||||
ME_InvalidateSelection(editor);
|
ME_InvalidateSelection(editor);
|
||||||
ME_ClearTempStyle(editor);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,13 +293,15 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start,
|
||||||
int nChars, BOOL bForce)
|
int nChars, BOOL bForce)
|
||||||
{
|
{
|
||||||
ME_Cursor c = *start;
|
ME_Cursor c = *start;
|
||||||
int nOfs = ME_GetCursorOfs(start);
|
int nOfs = ME_GetCursorOfs(start), text_len = ME_GetTextLength( editor );
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
int totalChars = nChars;
|
int totalChars = nChars;
|
||||||
ME_DisplayItem *start_para;
|
ME_DisplayItem *start_para;
|
||||||
|
BOOL delete_all = FALSE;
|
||||||
|
|
||||||
/* Prevent deletion past last end of paragraph run. */
|
/* Prevent deletion past last end of paragraph run. */
|
||||||
nChars = min(nChars, ME_GetTextLength(editor) - nOfs);
|
nChars = min(nChars, text_len - nOfs);
|
||||||
|
if (nChars == text_len) delete_all = TRUE;
|
||||||
start_para = c.pPara;
|
start_para = c.pPara;
|
||||||
|
|
||||||
if (!bForce)
|
if (!bForce)
|
||||||
|
@ -423,6 +435,7 @@ BOOL ME_InternalDeleteText(ME_TextEditor *editor, ME_Cursor *start,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (delete_all) ME_SetDefaultParaFormat( start_para->member.para.pFmt );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +539,7 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||||
ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
|
ME_InternalInsertTextFromCursor(editor, nCursor, &tab, 1, style, MERF_TAB);
|
||||||
pos++;
|
pos++;
|
||||||
} else { /* handle EOLs */
|
} else { /* handle EOLs */
|
||||||
ME_DisplayItem *tp, *end_run;
|
ME_DisplayItem *tp, *end_run, *run, *prev;
|
||||||
ME_Style *tmp_style;
|
ME_Style *tmp_style;
|
||||||
int eol_len = 0;
|
int eol_len = 0;
|
||||||
|
|
||||||
|
@ -560,17 +573,43 @@ void ME_InsertTextFromCursor(ME_TextEditor *editor, int nCursor,
|
||||||
}
|
}
|
||||||
|
|
||||||
p = &editor->pCursors[nCursor];
|
p = &editor->pCursors[nCursor];
|
||||||
if (p->nOffset)
|
|
||||||
ME_SplitRunSimple(editor, p);
|
if (p->nOffset == p->pRun->member.run.len)
|
||||||
|
{
|
||||||
|
run = ME_FindItemFwd( p->pRun, diRun );
|
||||||
|
if (!run) run = p->pRun;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (p->nOffset) ME_SplitRunSimple(editor, p);
|
||||||
|
run = p->pRun;
|
||||||
|
}
|
||||||
|
|
||||||
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
tmp_style = ME_GetInsertStyle(editor, nCursor);
|
||||||
/* ME_SplitParagraph increases style refcount */
|
/* ME_SplitParagraph increases style refcount */
|
||||||
tp = ME_SplitParagraph(editor, p->pRun, p->pRun->member.run.style, eol_str, eol_len, 0);
|
tp = ME_SplitParagraph(editor, run, run->member.run.style, eol_str, eol_len, 0);
|
||||||
p->pRun = ME_FindItemFwd(tp, diRun);
|
|
||||||
p->pPara = tp;
|
|
||||||
end_run = ME_FindItemBack(tp, diRun);
|
end_run = ME_FindItemBack(tp, diRun);
|
||||||
ME_ReleaseStyle(end_run->member.run.style);
|
ME_ReleaseStyle(end_run->member.run.style);
|
||||||
end_run->member.run.style = tmp_style;
|
end_run->member.run.style = tmp_style;
|
||||||
p->nOffset = 0;
|
|
||||||
|
/* Move any cursors that were at the end of the previous run to the beginning of the new para */
|
||||||
|
prev = ME_FindItemBack( end_run, diRun );
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < editor->nCursors; i++)
|
||||||
|
{
|
||||||
|
if (editor->pCursors[i].pRun == prev &&
|
||||||
|
editor->pCursors[i].nOffset == prev->member.run.len)
|
||||||
|
{
|
||||||
|
editor->pCursors[i].pPara = tp;
|
||||||
|
editor->pCursors[i].pRun = run;
|
||||||
|
editor->pCursors[i].nOffset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
len -= pos - str;
|
len -= pos - str;
|
||||||
|
@ -865,7 +904,7 @@ static ME_DisplayItem* ME_FindPixelPosInTableRow(int x, int y,
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow,
|
static BOOL ME_FindRunInRow(ME_TextEditor *editor, ME_DisplayItem *pRow,
|
||||||
int x, ME_Cursor *cursor, int *pbCaretAtEnd)
|
int x, ME_Cursor *cursor, BOOL *pbCaretAtEnd)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *pNext, *pLastRun;
|
ME_DisplayItem *pNext, *pLastRun;
|
||||||
ME_Row *row = &pRow->member.row;
|
ME_Row *row = &pRow->member.row;
|
||||||
|
@ -925,7 +964,7 @@ static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
|
||||||
y -= editor->rcFormat.top;
|
y -= editor->rcFormat.top;
|
||||||
|
|
||||||
if (is_eol)
|
if (is_eol)
|
||||||
*is_eol = 0;
|
*is_eol = FALSE;
|
||||||
|
|
||||||
/* find paragraph */
|
/* find paragraph */
|
||||||
for (; p != editor->pBuffer->pLast; p = p->member.para.next_para)
|
for (; p != editor->pBuffer->pLast; p = p->member.para.next_para)
|
||||||
|
@ -1070,8 +1109,7 @@ static void ME_ExtendAnchorSelection(ME_TextEditor *editor)
|
||||||
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
|
void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
|
||||||
{
|
{
|
||||||
ME_Cursor tmp_cursor;
|
ME_Cursor tmp_cursor;
|
||||||
int is_selection = 0;
|
BOOL is_selection = FALSE, is_shift;
|
||||||
BOOL is_shift;
|
|
||||||
|
|
||||||
editor->nUDArrowX = -1;
|
editor->nUDArrowX = -1;
|
||||||
|
|
||||||
|
@ -1128,7 +1166,6 @@ void ME_LButtonDown(ME_TextEditor *editor, int x, int y, int clickNum)
|
||||||
ME_InvalidateSelection(editor);
|
ME_InvalidateSelection(editor);
|
||||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
||||||
ME_ShowCaret(editor);
|
ME_ShowCaret(editor);
|
||||||
ME_ClearTempStyle(editor);
|
|
||||||
ME_SendSelChange(editor);
|
ME_SendSelChange(editor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,7 +1484,9 @@ void ME_DeleteSelection(ME_TextEditor *editor)
|
||||||
{
|
{
|
||||||
int from, to;
|
int from, to;
|
||||||
int nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
|
int nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
|
||||||
|
int nEndCursor = nStartCursor ^ 1;
|
||||||
ME_DeleteTextAtCursor(editor, nStartCursor, to - from);
|
ME_DeleteTextAtCursor(editor, nStartCursor, to - from);
|
||||||
|
editor->pCursors[nEndCursor] = editor->pCursors[nStartCursor];
|
||||||
}
|
}
|
||||||
|
|
||||||
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor)
|
ME_Style *ME_GetSelectionInsertStyle(ME_TextEditor *editor)
|
||||||
|
@ -1495,14 +1534,14 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
|
||||||
ME_CheckCharOffsets(editor);
|
ME_CheckCharOffsets(editor);
|
||||||
switch(nVKey) {
|
switch(nVKey) {
|
||||||
case VK_LEFT:
|
case VK_LEFT:
|
||||||
editor->bCaretAtEnd = 0;
|
editor->bCaretAtEnd = FALSE;
|
||||||
if (ctrl)
|
if (ctrl)
|
||||||
success = ME_MoveCursorWords(editor, &tmp_curs, -1);
|
success = ME_MoveCursorWords(editor, &tmp_curs, -1);
|
||||||
else
|
else
|
||||||
success = ME_MoveCursorChars(editor, &tmp_curs, -1);
|
success = ME_MoveCursorChars(editor, &tmp_curs, -1);
|
||||||
break;
|
break;
|
||||||
case VK_RIGHT:
|
case VK_RIGHT:
|
||||||
editor->bCaretAtEnd = 0;
|
editor->bCaretAtEnd = FALSE;
|
||||||
if (ctrl)
|
if (ctrl)
|
||||||
success = ME_MoveCursorWords(editor, &tmp_curs, +1);
|
success = ME_MoveCursorWords(editor, &tmp_curs, +1);
|
||||||
else
|
else
|
||||||
|
@ -1525,7 +1564,7 @@ ME_ArrowKey(ME_TextEditor *editor, int nVKey, BOOL extend, BOOL ctrl)
|
||||||
ME_ArrowCtrlHome(editor, &tmp_curs);
|
ME_ArrowCtrlHome(editor, &tmp_curs);
|
||||||
else
|
else
|
||||||
ME_ArrowHome(editor, &tmp_curs);
|
ME_ArrowHome(editor, &tmp_curs);
|
||||||
editor->bCaretAtEnd = 0;
|
editor->bCaretAtEnd = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case VK_END:
|
case VK_END:
|
||||||
|
|
|
@ -245,13 +245,13 @@ static const WCHAR REListBox20W[] = {'R','E','L','i','s','t','B','o','x','2','0'
|
||||||
static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0};
|
static const WCHAR REComboBox20W[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0};
|
||||||
static HCURSOR hLeft;
|
static HCURSOR hLeft;
|
||||||
|
|
||||||
int me_debug = 0;
|
BOOL me_debug = FALSE;
|
||||||
HANDLE me_heap = NULL;
|
HANDLE me_heap = NULL;
|
||||||
|
|
||||||
static BOOL ME_ListBoxRegistered = FALSE;
|
static BOOL ME_ListBoxRegistered = FALSE;
|
||||||
static BOOL ME_ComboBoxRegistered = FALSE;
|
static BOOL ME_ComboBoxRegistered = FALSE;
|
||||||
|
|
||||||
static inline int is_version_nt(void)
|
static inline BOOL is_version_nt(void)
|
||||||
{
|
{
|
||||||
return !(GetVersion() & 0x80000000);
|
return !(GetVersion() & 0x80000000);
|
||||||
}
|
}
|
||||||
|
@ -284,6 +284,9 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea
|
||||||
WCHAR *pText;
|
WCHAR *pText;
|
||||||
LRESULT total_bytes_read = 0;
|
LRESULT total_bytes_read = 0;
|
||||||
BOOL is_read = FALSE;
|
BOOL is_read = FALSE;
|
||||||
|
DWORD cp = CP_ACP, copy = 0;
|
||||||
|
char conv_buf[4 + STREAMIN_BUFFER_SIZE]; /* up to 4 additional UTF-8 bytes */
|
||||||
|
|
||||||
static const char bom_utf8[] = {0xEF, 0xBB, 0xBF};
|
static const char bom_utf8[] = {0xEF, 0xBB, 0xBF};
|
||||||
|
|
||||||
TRACE("%08x %p\n", dwFormat, stream);
|
TRACE("%08x %p\n", dwFormat, stream);
|
||||||
|
@ -305,8 +308,7 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea
|
||||||
if (!(dwFormat & SF_UNICODE))
|
if (!(dwFormat & SF_UNICODE))
|
||||||
{
|
{
|
||||||
char * buf = stream->buffer;
|
char * buf = stream->buffer;
|
||||||
DWORD size = stream->dwSize;
|
DWORD size = stream->dwSize, end;
|
||||||
DWORD cp = CP_ACP;
|
|
||||||
|
|
||||||
if (!is_read)
|
if (!is_read)
|
||||||
{
|
{
|
||||||
|
@ -319,8 +321,56 @@ static LRESULT ME_StreamInText(ME_TextEditor *editor, DWORD dwFormat, ME_InStrea
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nWideChars = MultiByteToWideChar(cp, 0, buf, size, wszText, STREAMIN_BUFFER_SIZE);
|
if (cp == CP_UTF8)
|
||||||
|
{
|
||||||
|
if (copy)
|
||||||
|
{
|
||||||
|
memcpy(conv_buf + copy, buf, size);
|
||||||
|
buf = conv_buf;
|
||||||
|
size += copy;
|
||||||
|
}
|
||||||
|
end = size;
|
||||||
|
while ((buf[end-1] & 0xC0) == 0x80)
|
||||||
|
{
|
||||||
|
--end;
|
||||||
|
--total_bytes_read; /* strange, but seems to match windows */
|
||||||
|
}
|
||||||
|
if (buf[end-1] & 0x80)
|
||||||
|
{
|
||||||
|
DWORD need = 0;
|
||||||
|
if ((buf[end-1] & 0xE0) == 0xC0)
|
||||||
|
need = 1;
|
||||||
|
if ((buf[end-1] & 0xF0) == 0xE0)
|
||||||
|
need = 2;
|
||||||
|
if ((buf[end-1] & 0xF8) == 0xF0)
|
||||||
|
need = 3;
|
||||||
|
|
||||||
|
if (size - end >= need)
|
||||||
|
{
|
||||||
|
/* we have enough bytes for this sequence */
|
||||||
|
end = size;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* need more bytes, so don't transcode this sequence */
|
||||||
|
--end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
end = size;
|
||||||
|
|
||||||
|
nWideChars = MultiByteToWideChar(cp, 0, buf, end, wszText, STREAMIN_BUFFER_SIZE);
|
||||||
pText = wszText;
|
pText = wszText;
|
||||||
|
|
||||||
|
if (cp == CP_UTF8)
|
||||||
|
{
|
||||||
|
if (end != size)
|
||||||
|
{
|
||||||
|
memcpy(conv_buf, buf + end, size - end);
|
||||||
|
copy = size - end;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1146,11 +1196,8 @@ static BOOL ME_RTFInsertOleObject(RTF_Info *info, HENHMETAFILE hemf, HBITMAP hbm
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK &&
|
if (OleCreateDefaultHandler(&CLSID_NULL, NULL, &IID_IOleObject, (void**)&lpObject) == S_OK &&
|
||||||
#if 0
|
|
||||||
/* FIXME: enable it when rich-edit properly implements this method */
|
|
||||||
IRichEditOle_GetClientSite(info->lpRichEditOle, &lpClientSite) == S_OK &&
|
IRichEditOle_GetClientSite(info->lpRichEditOle, &lpClientSite) == S_OK &&
|
||||||
IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK &&
|
IOleObject_SetClientSite(lpObject, lpClientSite) == S_OK &&
|
||||||
#endif
|
|
||||||
IOleObject_GetUserClassID(lpObject, &clsid) == S_OK &&
|
IOleObject_GetUserClassID(lpObject, &clsid) == S_OK &&
|
||||||
IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK &&
|
IOleObject_QueryInterface(lpObject, &IID_IOleCache, (void**)&lpOleCache) == S_OK &&
|
||||||
IOleCache_Cache(lpOleCache, &fm, 0, &conn) == S_OK &&
|
IOleCache_Cache(lpOleCache, &fm, 0, &conn) == S_OK &&
|
||||||
|
@ -1581,7 +1628,7 @@ static LRESULT ME_StreamIn(ME_TextEditor *editor, DWORD format, EDITSTREAM *stre
|
||||||
ME_Cursor linebreakCursor = *selEnd;
|
ME_Cursor linebreakCursor = *selEnd;
|
||||||
|
|
||||||
ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize);
|
ME_MoveCursorChars(editor, &linebreakCursor, -linebreakSize);
|
||||||
ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, 0);
|
ME_GetTextW(editor, lastchar, 2, &linebreakCursor, linebreakSize, FALSE);
|
||||||
if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) {
|
if (lastchar[0] == '\r' && (lastchar[1] == '\n' || lastchar[1] == '\0')) {
|
||||||
ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE);
|
ME_InternalDeleteText(editor, &linebreakCursor, linebreakSize, FALSE);
|
||||||
}
|
}
|
||||||
|
@ -1916,7 +1963,7 @@ static int ME_GetTextEx(ME_TextEditor *editor, GETTEXTEX *ex, LPARAM pText)
|
||||||
ME_SetCursorToStart(editor, &start);
|
ME_SetCursorToStart(editor, &start);
|
||||||
nChars = INT_MAX;
|
nChars = INT_MAX;
|
||||||
}
|
}
|
||||||
if (ex->codepage == 1200)
|
if (ex->codepage == CP_UNICODE)
|
||||||
{
|
{
|
||||||
return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1,
|
return ME_GetTextW(editor, (LPWSTR)pText, ex->cb / sizeof(WCHAR) - 1,
|
||||||
&start, nChars, ex->flags & GT_USECRLF);
|
&start, nChars, ex->flags & GT_USECRLF);
|
||||||
|
@ -1951,12 +1998,12 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText,
|
||||||
{
|
{
|
||||||
if (!strText) return 0;
|
if (!strText) return 0;
|
||||||
if (unicode) {
|
if (unicode) {
|
||||||
return ME_GetTextW(editor, strText, INT_MAX, start, nLen, 0);
|
return ME_GetTextW(editor, strText, INT_MAX, start, nLen, FALSE);
|
||||||
} else {
|
} else {
|
||||||
int nChars;
|
int nChars;
|
||||||
WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
|
WCHAR *p = ALLOC_N_OBJ(WCHAR, nLen+1);
|
||||||
if (!p) return 0;
|
if (!p) return 0;
|
||||||
nChars = ME_GetTextW(editor, p, nLen, start, nLen, 0);
|
nChars = ME_GetTextW(editor, p, nLen, start, nLen, FALSE);
|
||||||
WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText,
|
WideCharToMultiByte(CP_ACP, 0, p, nChars+1, (char *)strText,
|
||||||
nLen+1, NULL, NULL);
|
nLen+1, NULL, NULL);
|
||||||
FREE_OBJ(p);
|
FREE_OBJ(p);
|
||||||
|
@ -1964,6 +2011,22 @@ static int ME_GetTextRange(ME_TextEditor *editor, WCHAR *strText,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int handle_EM_EXSETSEL( ME_TextEditor *editor, int to, int from )
|
||||||
|
{
|
||||||
|
int end;
|
||||||
|
|
||||||
|
TRACE("%d - %d\n", to, from );
|
||||||
|
|
||||||
|
ME_InvalidateSelection( editor );
|
||||||
|
end = ME_SetSelection( editor, to, from );
|
||||||
|
ME_InvalidateSelection( editor );
|
||||||
|
ITextHost_TxShowCaret( editor->texthost, FALSE );
|
||||||
|
ME_ShowCaret( editor );
|
||||||
|
ME_SendSelChange( editor );
|
||||||
|
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct tagME_GlobalDestStruct
|
typedef struct tagME_GlobalDestStruct
|
||||||
{
|
{
|
||||||
HGLOBAL hData;
|
HGLOBAL hData;
|
||||||
|
@ -2331,7 +2394,7 @@ ME_KeyDown(ME_TextEditor *editor, WORD nKey)
|
||||||
case 'A':
|
case 'A':
|
||||||
if (ctrl_is_down)
|
if (ctrl_is_down)
|
||||||
{
|
{
|
||||||
ME_SetSelection(editor, 0, -1);
|
handle_EM_EXSETSEL( editor, 0, -1 );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2790,6 +2853,8 @@ ME_TextEditor *ME_MakeEditor(ITextHost *texthost, BOOL bEmulateVersion10)
|
||||||
ed->horz_si.nPage = 0;
|
ed->horz_si.nPage = 0;
|
||||||
ed->horz_si.nPos = 0;
|
ed->horz_si.nPos = 0;
|
||||||
|
|
||||||
|
ed->wheel_remain = 0;
|
||||||
|
|
||||||
OleInitialize(NULL);
|
OleInitialize(NULL);
|
||||||
|
|
||||||
return ed;
|
return ed;
|
||||||
|
@ -2857,6 +2922,23 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int get_default_line_height( ME_TextEditor *editor )
|
||||||
|
{
|
||||||
|
int height = 0;
|
||||||
|
|
||||||
|
if (editor->pBuffer && editor->pBuffer->pDefaultStyle)
|
||||||
|
height = editor->pBuffer->pDefaultStyle->tm.tmHeight;
|
||||||
|
if (height <= 0) height = 24;
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int calc_wheel_change( int *remain, int amount_per_click )
|
||||||
|
{
|
||||||
|
int change = amount_per_click * (float)*remain / WHEEL_DELTA;
|
||||||
|
*remain -= WHEEL_DELTA * change / amount_per_click;
|
||||||
|
return change;
|
||||||
|
}
|
||||||
|
|
||||||
static const char * const edit_messages[] = {
|
static const char * const edit_messages[] = {
|
||||||
"EM_GETSEL",
|
"EM_GETSEL",
|
||||||
|
@ -3074,11 +3156,14 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
return ME_StreamOut(editor, wParam, (EDITSTREAM *)lParam);
|
return ME_StreamOut(editor, wParam, (EDITSTREAM *)lParam);
|
||||||
case WM_GETDLGCODE:
|
case WM_GETDLGCODE:
|
||||||
{
|
{
|
||||||
UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS|DLGC_HASSETSEL;
|
UINT code = DLGC_WANTCHARS|DLGC_WANTTAB|DLGC_WANTARROWS;
|
||||||
|
|
||||||
if (lParam)
|
if (lParam)
|
||||||
editor->bDialogMode = TRUE;
|
editor->bDialogMode = TRUE;
|
||||||
if (editor->styleFlags & ES_MULTILINE)
|
if (editor->styleFlags & ES_MULTILINE)
|
||||||
code |= DLGC_WANTMESSAGE;
|
code |= DLGC_WANTMESSAGE;
|
||||||
|
if (!(editor->styleFlags & ES_SAVESEL))
|
||||||
|
code |= DLGC_HASSETSEL;
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
case EM_EMPTYUNDOBUFFER:
|
case EM_EMPTYUNDOBUFFER:
|
||||||
|
@ -3194,12 +3279,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
case EM_SETSEL:
|
case EM_SETSEL:
|
||||||
{
|
{
|
||||||
ME_InvalidateSelection(editor);
|
handle_EM_EXSETSEL( editor, wParam, lParam );
|
||||||
ME_SetSelection(editor, wParam, lParam);
|
|
||||||
ME_InvalidateSelection(editor);
|
|
||||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
|
||||||
ME_ShowCaret(editor);
|
|
||||||
ME_SendSelChange(editor);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
case EM_SETSCROLLPOS:
|
case EM_SETSCROLLPOS:
|
||||||
|
@ -3223,19 +3303,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
case EM_EXSETSEL:
|
case EM_EXSETSEL:
|
||||||
{
|
{
|
||||||
int end;
|
|
||||||
CHARRANGE range = *(CHARRANGE *)lParam;
|
CHARRANGE range = *(CHARRANGE *)lParam;
|
||||||
|
|
||||||
TRACE("EM_EXSETSEL (%d,%d)\n", range.cpMin, range.cpMax);
|
return handle_EM_EXSETSEL( editor, range.cpMin, range.cpMax );
|
||||||
|
|
||||||
ME_InvalidateSelection(editor);
|
|
||||||
end = ME_SetSelection(editor, range.cpMin, range.cpMax);
|
|
||||||
ME_InvalidateSelection(editor);
|
|
||||||
ITextHost_TxShowCaret(editor->texthost, FALSE);
|
|
||||||
ME_ShowCaret(editor);
|
|
||||||
ME_SendSelChange(editor);
|
|
||||||
|
|
||||||
return end;
|
|
||||||
}
|
}
|
||||||
case EM_SHOWSCROLLBAR:
|
case EM_SHOWSCROLLBAR:
|
||||||
{
|
{
|
||||||
|
@ -3274,11 +3344,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
{
|
{
|
||||||
LPWSTR wszText;
|
LPWSTR wszText;
|
||||||
SETTEXTEX *pStruct = (SETTEXTEX *)wParam;
|
SETTEXTEX *pStruct = (SETTEXTEX *)wParam;
|
||||||
size_t len = 0;
|
int from, to, len;
|
||||||
int from, to;
|
|
||||||
ME_Style *style;
|
ME_Style *style;
|
||||||
BOOL bRtf, bUnicode, bSelection;
|
BOOL bRtf, bUnicode, bSelection, bUTF8;
|
||||||
int oldModify = editor->nModifyStep;
|
int oldModify = editor->nModifyStep;
|
||||||
|
static const char utf8_bom[] = {0xef, 0xbb, 0xbf};
|
||||||
|
|
||||||
if (!pStruct) return 0;
|
if (!pStruct) return 0;
|
||||||
|
|
||||||
|
@ -3286,7 +3356,8 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
* we know it isn't unicode. */
|
* we know it isn't unicode. */
|
||||||
bRtf = (lParam && (!strncmp((char *)lParam, "{\\rtf", 5) ||
|
bRtf = (lParam && (!strncmp((char *)lParam, "{\\rtf", 5) ||
|
||||||
!strncmp((char *)lParam, "{\\urtf", 6)));
|
!strncmp((char *)lParam, "{\\urtf", 6)));
|
||||||
bUnicode = !bRtf && pStruct->codepage == 1200;
|
bUnicode = !bRtf && pStruct->codepage == CP_UNICODE;
|
||||||
|
bUTF8 = (lParam && (!strncmp((char *)lParam, utf8_bom, 3)));
|
||||||
|
|
||||||
TRACE("EM_SETTEXTEX - %s, flags %d, cp %d\n",
|
TRACE("EM_SETTEXTEX - %s, flags %d, cp %d\n",
|
||||||
bUnicode ? debugstr_w((LPCWSTR)lParam) : debugstr_a((LPCSTR)lParam),
|
bUnicode ? debugstr_w((LPCWSTR)lParam) : debugstr_a((LPCSTR)lParam),
|
||||||
|
@ -3312,11 +3383,15 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
len = lParam ? strlen((char *)lParam) : 0;
|
len = lParam ? strlen((char *)lParam) : 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* FIXME: make use of pStruct->codepage in the to unicode translation */
|
if (bUTF8 && !bUnicode) {
|
||||||
wszText = lParam ? ME_ToUnicode(bUnicode, (void *)lParam) : NULL;
|
wszText = ME_ToUnicode(CP_UTF8, (void *)(lParam+3), &len);
|
||||||
len = wszText ? lstrlenW(wszText) : 0;
|
|
||||||
ME_InsertTextFromCursor(editor, 0, wszText, len, style);
|
ME_InsertTextFromCursor(editor, 0, wszText, len, style);
|
||||||
ME_EndToUnicode(bUnicode, wszText);
|
ME_EndToUnicode(CP_UTF8, wszText);
|
||||||
|
} else {
|
||||||
|
wszText = ME_ToUnicode(pStruct->codepage, (void *)lParam, &len);
|
||||||
|
ME_InsertTextFromCursor(editor, 0, wszText, len, style);
|
||||||
|
ME_EndToUnicode(pStruct->codepage, wszText);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bSelection) {
|
if (bSelection) {
|
||||||
|
@ -3487,7 +3562,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
{
|
{
|
||||||
if (!(editor->styleFlags & ES_MULTILINE))
|
if (!(editor->styleFlags & ES_MULTILINE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
ME_ScrollDown(editor, lParam * 8); /* FIXME follow the original */
|
ME_ScrollDown( editor, lParam * get_default_line_height( editor ) );
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
case WM_CLEAR:
|
case WM_CLEAR:
|
||||||
|
@ -3503,8 +3578,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
{
|
{
|
||||||
int from, to, nStartCursor;
|
int from, to, nStartCursor;
|
||||||
ME_Style *style;
|
ME_Style *style;
|
||||||
LPWSTR wszText = lParam ? ME_ToUnicode(unicode, (void *)lParam) : NULL;
|
int len = 0;
|
||||||
size_t len = wszText ? lstrlenW(wszText) : 0;
|
LONG codepage = unicode ? CP_UNICODE : CP_ACP;
|
||||||
|
LPWSTR wszText = ME_ToUnicode(codepage, (void *)lParam, &len);
|
||||||
TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
|
TRACE("EM_REPLACESEL - %s\n", debugstr_w(wszText));
|
||||||
|
|
||||||
nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
|
nStartCursor = ME_GetSelectionOfs(editor, &from, &to);
|
||||||
|
@ -3519,7 +3595,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
*/
|
*/
|
||||||
if (len>0 && wszText[len-1] == '\n')
|
if (len>0 && wszText[len-1] == '\n')
|
||||||
ME_ClearTempStyle(editor);
|
ME_ClearTempStyle(editor);
|
||||||
ME_EndToUnicode(unicode, wszText);
|
ME_EndToUnicode(codepage, wszText);
|
||||||
ME_CommitUndo(editor);
|
ME_CommitUndo(editor);
|
||||||
ME_UpdateSelectionLinkAttribute(editor);
|
ME_UpdateSelectionLinkAttribute(editor);
|
||||||
if (!wParam)
|
if (!wParam)
|
||||||
|
@ -3574,9 +3650,11 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LPWSTR wszText = ME_ToUnicode(unicode, (void *)lParam);
|
int textLen;
|
||||||
|
LONG codepage = unicode ? CP_UNICODE : CP_ACP;
|
||||||
|
LPWSTR wszText = ME_ToUnicode(codepage, (void *)lParam, &textLen);
|
||||||
TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
|
TRACE("WM_SETTEXT - %s\n", debugstr_w(wszText)); /* debugstr_w() */
|
||||||
if (lstrlenW(wszText) > 0)
|
if (textLen > 0)
|
||||||
{
|
{
|
||||||
int len = -1;
|
int len = -1;
|
||||||
|
|
||||||
|
@ -3591,7 +3669,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle);
|
ME_InsertTextFromCursor(editor, 0, wszText, len, editor->pBuffer->pDefaultStyle);
|
||||||
}
|
}
|
||||||
ME_EndToUnicode(unicode, wszText);
|
ME_EndToUnicode(codepage, wszText);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -3639,7 +3717,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
|
|
||||||
/* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */
|
/* CR/LF conversion required in 2.0 mode, verbatim in 1.0 mode */
|
||||||
how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS;
|
how.flags = GTL_CLOSE | (editor->bEmulateVersion10 ? 0 : GTL_USECRLF) | GTL_NUMCHARS;
|
||||||
how.codepage = unicode ? 1200 : CP_ACP;
|
how.codepage = unicode ? CP_UNICODE : CP_ACP;
|
||||||
return ME_GetTextLengthEx(editor, &how);
|
return ME_GetTextLengthEx(editor, &how);
|
||||||
}
|
}
|
||||||
case EM_GETTEXTLENGTHEX:
|
case EM_GETTEXTLENGTHEX:
|
||||||
|
@ -3649,7 +3727,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
GETTEXTEX ex;
|
GETTEXTEX ex;
|
||||||
ex.cb = wParam * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
|
ex.cb = wParam * (unicode ? sizeof(WCHAR) : sizeof(CHAR));
|
||||||
ex.flags = GT_USECRLF;
|
ex.flags = GT_USECRLF;
|
||||||
ex.codepage = unicode ? 1200 : CP_ACP;
|
ex.codepage = unicode ? CP_UNICODE : CP_ACP;
|
||||||
ex.lpDefaultChar = NULL;
|
ex.lpDefaultChar = NULL;
|
||||||
ex.lpUsedDefChar = NULL;
|
ex.lpUsedDefChar = NULL;
|
||||||
return ME_GetTextEx(editor, &ex, lParam);
|
return ME_GetTextEx(editor, &ex, lParam);
|
||||||
|
@ -3948,6 +4026,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
case WM_CREATE:
|
case WM_CREATE:
|
||||||
{
|
{
|
||||||
|
void *text = NULL;
|
||||||
INT max;
|
INT max;
|
||||||
|
|
||||||
ME_SetDefaultFormatRect(editor);
|
ME_SetDefaultFormatRect(editor);
|
||||||
|
@ -3973,6 +4052,29 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lParam)
|
||||||
|
{
|
||||||
|
text = (unicode ? (void*)((CREATESTRUCTW*)lParam)->lpszName
|
||||||
|
: (void*)((CREATESTRUCTA*)lParam)->lpszName);
|
||||||
|
}
|
||||||
|
if (text)
|
||||||
|
{
|
||||||
|
WCHAR *textW;
|
||||||
|
int len;
|
||||||
|
LONG codepage = unicode ? CP_UNICODE : CP_ACP;
|
||||||
|
textW = ME_ToUnicode(codepage, text, &len);
|
||||||
|
if (!(editor->styleFlags & ES_MULTILINE))
|
||||||
|
{
|
||||||
|
len = 0;
|
||||||
|
while(textW[len] != '\0' && textW[len] != '\r' && textW[len] != '\n')
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
ME_InsertTextFromCursor(editor, 0, textW, len, editor->pBuffer->pDefaultStyle);
|
||||||
|
ME_EndToUnicode(codepage, textW);
|
||||||
|
ME_SetCursorToStart(editor, &editor->pCursors[0]);
|
||||||
|
ME_SetCursorToStart(editor, &editor->pCursors[1]);
|
||||||
|
}
|
||||||
|
|
||||||
ME_CommitUndo(editor);
|
ME_CommitUndo(editor);
|
||||||
ME_WrapMarkedParagraphs(editor);
|
ME_WrapMarkedParagraphs(editor);
|
||||||
ME_MoveCaret(editor);
|
ME_MoveCaret(editor);
|
||||||
|
@ -4047,6 +4149,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
case WM_KILLFOCUS:
|
case WM_KILLFOCUS:
|
||||||
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
|
ME_CommitUndo(editor); /* End coalesced undos for typed characters */
|
||||||
editor->bHaveFocus = FALSE;
|
editor->bHaveFocus = FALSE;
|
||||||
|
editor->wheel_remain = 0;
|
||||||
ME_HideCaret(editor);
|
ME_HideCaret(editor);
|
||||||
ME_SendOldNotify(editor, EN_KILLFOCUS);
|
ME_SendOldNotify(editor, EN_KILLFOCUS);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -4133,14 +4236,9 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
case WM_VSCROLL:
|
case WM_VSCROLL:
|
||||||
{
|
{
|
||||||
int origNPos;
|
int origNPos;
|
||||||
int lineHeight;
|
int lineHeight = get_default_line_height( editor );
|
||||||
|
|
||||||
origNPos = editor->vert_si.nPos;
|
origNPos = editor->vert_si.nPos;
|
||||||
lineHeight = 24;
|
|
||||||
|
|
||||||
if (editor->pBuffer && editor->pBuffer->pDefaultStyle)
|
|
||||||
lineHeight = editor->pBuffer->pDefaultStyle->tm.tmHeight;
|
|
||||||
if (lineHeight <= 0) lineHeight = 24;
|
|
||||||
|
|
||||||
switch(LOWORD(wParam))
|
switch(LOWORD(wParam))
|
||||||
{
|
{
|
||||||
|
@ -4180,8 +4278,7 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
}
|
}
|
||||||
case WM_MOUSEWHEEL:
|
case WM_MOUSEWHEEL:
|
||||||
{
|
{
|
||||||
int gcWheelDelta;
|
int delta;
|
||||||
UINT pulScrollLines;
|
|
||||||
BOOL ctrl_is_down;
|
BOOL ctrl_is_down;
|
||||||
|
|
||||||
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
|
if ((editor->nEventMask & ENM_MOUSEEVENTS) &&
|
||||||
|
@ -4190,9 +4287,16 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
|
|
||||||
ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000;
|
ctrl_is_down = GetKeyState(VK_CONTROL) & 0x8000;
|
||||||
|
|
||||||
gcWheelDelta = GET_WHEEL_DELTA_WPARAM(wParam);
|
delta = GET_WHEEL_DELTA_WPARAM(wParam);
|
||||||
|
|
||||||
if (abs(gcWheelDelta) >= WHEEL_DELTA)
|
/* if scrolling changes direction, ignore left overs */
|
||||||
|
if ((delta < 0 && editor->wheel_remain < 0) ||
|
||||||
|
(delta > 0 && editor->wheel_remain > 0))
|
||||||
|
editor->wheel_remain += delta;
|
||||||
|
else
|
||||||
|
editor->wheel_remain = delta;
|
||||||
|
|
||||||
|
if (editor->wheel_remain)
|
||||||
{
|
{
|
||||||
if (ctrl_is_down) {
|
if (ctrl_is_down) {
|
||||||
int numerator;
|
int numerator;
|
||||||
|
@ -4202,14 +4306,18 @@ LRESULT ME_HandleMessage(ME_TextEditor *editor, UINT msg, WPARAM wParam,
|
||||||
} else {
|
} else {
|
||||||
numerator = editor->nZoomNumerator * 100 / editor->nZoomDenominator;
|
numerator = editor->nZoomNumerator * 100 / editor->nZoomDenominator;
|
||||||
}
|
}
|
||||||
numerator = numerator + (gcWheelDelta / WHEEL_DELTA) * 10;
|
numerator += calc_wheel_change( &editor->wheel_remain, 10 );
|
||||||
if (numerator >= 10 && numerator <= 500)
|
if (numerator >= 10 && numerator <= 500)
|
||||||
ME_SetZoom(editor, numerator, 100);
|
ME_SetZoom(editor, numerator, 100);
|
||||||
} else {
|
} else {
|
||||||
SystemParametersInfoW(SPI_GETWHEELSCROLLLINES,0, &pulScrollLines, 0);
|
UINT max_lines = 3;
|
||||||
/* FIXME follow the original */
|
int lines = 0;
|
||||||
if (pulScrollLines)
|
|
||||||
ME_ScrollDown(editor,pulScrollLines * (-gcWheelDelta / WHEEL_DELTA) * 8);
|
SystemParametersInfoW( SPI_GETWHEELSCROLLLINES, 0, &max_lines, 0 );
|
||||||
|
if (max_lines)
|
||||||
|
lines = calc_wheel_change( &editor->wheel_remain, (int)max_lines );
|
||||||
|
if (lines)
|
||||||
|
ME_ScrollDown( editor, -lines * get_default_line_height( editor ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -4617,7 +4725,7 @@ int ME_GetTextW(ME_TextEditor *editor, WCHAR *buffer, int buflen,
|
||||||
int nLen;
|
int nLen;
|
||||||
|
|
||||||
/* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */
|
/* bCRLF flag is only honored in 2.0 and up. 1.0 must always return text verbatim */
|
||||||
if (editor->bEmulateVersion10) bCRLF = 0;
|
if (editor->bEmulateVersion10) bCRLF = FALSE;
|
||||||
|
|
||||||
pRun = start->pRun;
|
pRun = start->pRun;
|
||||||
assert(pRun);
|
assert(pRun);
|
||||||
|
@ -4902,7 +5010,7 @@ static BOOL ME_IsCandidateAnURL(ME_TextEditor *editor, const ME_Cursor *start, i
|
||||||
WCHAR bufferW[MAX_PREFIX_LEN + 1];
|
WCHAR bufferW[MAX_PREFIX_LEN + 1];
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, 0);
|
ME_GetTextW(editor, bufferW, MAX_PREFIX_LEN, start, nChars, FALSE);
|
||||||
for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++)
|
for (i = 0; i < sizeof(prefixes) / sizeof(*prefixes); i++)
|
||||||
{
|
{
|
||||||
if (nChars < prefixes[i].length) continue;
|
if (nChars < prefixes[i].length) continue;
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <richole.h>
|
#include <richole.h>
|
||||||
#include <imm.h>
|
#include <imm.h>
|
||||||
#include <textserv.h>
|
#include <textserv.h>
|
||||||
|
#include <usp10.h>
|
||||||
|
|
||||||
#include <wine/debug.h>
|
#include <wine/debug.h>
|
||||||
#include <wine/list.h>
|
#include <wine/list.h>
|
||||||
|
@ -128,7 +129,6 @@ ME_DisplayItem *ME_FindItemBackOrHere(ME_DisplayItem *di, ME_DIType nTypeOrClass
|
||||||
ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN;
|
ME_DisplayItem *ME_MakeDI(ME_DIType type) DECLSPEC_HIDDEN;
|
||||||
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN;
|
void ME_DestroyDisplayItem(ME_DisplayItem *item) DECLSPEC_HIDDEN;
|
||||||
void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
|
void ME_DumpDocument(ME_TextBuffer *buffer) DECLSPEC_HIDDEN;
|
||||||
const char *ME_GetDITypeName(ME_DIType type) DECLSPEC_HIDDEN;
|
|
||||||
|
|
||||||
/* string.c */
|
/* string.c */
|
||||||
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
|
ME_String *ME_MakeStringN(LPCWSTR szText, int nMaxChars) DECLSPEC_HIDDEN;
|
||||||
|
@ -141,9 +141,11 @@ int ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start,
|
||||||
void ME_StrDeleteV(ME_String *s, int nVChar, int nChars) DECLSPEC_HIDDEN;
|
void ME_StrDeleteV(ME_String *s, int nVChar, int nChars) DECLSPEC_HIDDEN;
|
||||||
BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len) DECLSPEC_HIDDEN;
|
BOOL ME_InsertString(ME_String *s, int ofs, const WCHAR *insert, int len) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
|
#define CP_UNICODE 1200
|
||||||
|
|
||||||
/* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */
|
/* smart helpers for A<->W conversions, they reserve/free memory and call MultiByte<->WideChar functions */
|
||||||
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz) DECLSPEC_HIDDEN;
|
LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len) DECLSPEC_HIDDEN;
|
||||||
void ME_EndToUnicode(BOOL unicode, LPVOID psz) DECLSPEC_HIDDEN;
|
void ME_EndToUnicode(LONG codepage, LPVOID psz) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
static inline int ME_IsWSpace(WCHAR ch)
|
static inline int ME_IsWSpace(WCHAR ch)
|
||||||
{
|
{
|
||||||
|
@ -177,7 +179,7 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO
|
||||||
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN;
|
int ME_CharFromPoint(ME_TextEditor *editor, int cx, ME_Run *run, BOOL closest, BOOL visual_order) DECLSPEC_HIDDEN;
|
||||||
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
|
int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
|
||||||
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
|
int ME_PointFromChar(ME_TextEditor *editor, ME_Run *pRun, int nOffset, BOOL visual_order) DECLSPEC_HIDDEN;
|
||||||
int ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN;
|
BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2) DECLSPEC_HIDDEN;
|
||||||
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN;
|
void ME_JoinRuns(ME_TextEditor *editor, ME_DisplayItem *p) DECLSPEC_HIDDEN;
|
||||||
ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
|
ME_DisplayItem *ME_SplitRunSimple(ME_TextEditor *editor, ME_Cursor *cursor) DECLSPEC_HIDDEN;
|
||||||
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) DECLSPEC_HIDDEN;
|
void ME_UpdateRunFlags(ME_TextEditor *editor, ME_Run *run) DECLSPEC_HIDDEN;
|
||||||
|
@ -290,7 +292,7 @@ void ME_RTFParAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
|
||||||
void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
|
void ME_RTFTblAttrHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
|
||||||
void ME_RTFSpecialCharHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
|
void ME_RTFSpecialCharHook(struct _RTF_Info *info) DECLSPEC_HIDDEN;
|
||||||
void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN;
|
void ME_StreamInFill(ME_InStream *stream) DECLSPEC_HIDDEN;
|
||||||
extern int me_debug DECLSPEC_HIDDEN;
|
extern BOOL me_debug DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* table.c */
|
/* table.c */
|
||||||
BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN;
|
BOOL ME_IsInTable(ME_DisplayItem *pItem) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -38,6 +38,7 @@ typedef struct tagME_Style
|
||||||
HFONT hFont; /* cached font for the style */
|
HFONT hFont; /* cached font for the style */
|
||||||
TEXTMETRICW tm; /* cached font metrics for the style */
|
TEXTMETRICW tm; /* cached font metrics for the style */
|
||||||
int nRefs; /* reference count */
|
int nRefs; /* reference count */
|
||||||
|
SCRIPT_CACHE script_cache;
|
||||||
} ME_Style;
|
} ME_Style;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -104,6 +105,7 @@ typedef enum {
|
||||||
#define MEPF_CELL 0x04 /* The paragraph is nested in a cell */
|
#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_ROWSTART 0x08 /* Hidden empty paragraph at the start of the row */
|
||||||
#define MEPF_ROWEND 0x10 /* Visible empty paragraph at the end of the row */
|
#define MEPF_ROWEND 0x10 /* Visible empty paragraph at the end of the row */
|
||||||
|
#define MEPF_COMPLEX 0x20 /* Use uniscribe */
|
||||||
|
|
||||||
/******************************** structures *************************/
|
/******************************** structures *************************/
|
||||||
|
|
||||||
|
@ -120,6 +122,15 @@ typedef struct tagME_Run
|
||||||
int nAscent, nDescent; /* pixels above/below baseline */
|
int nAscent, nDescent; /* pixels above/below baseline */
|
||||||
POINT pt; /* relative to para's position */
|
POINT pt; /* relative to para's position */
|
||||||
REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */
|
REOBJECT *ole_obj; /* FIXME: should be a union with strText (at least) */
|
||||||
|
|
||||||
|
SCRIPT_ANALYSIS script_analysis;
|
||||||
|
int num_glyphs, max_glyphs;
|
||||||
|
WORD *glyphs;
|
||||||
|
SCRIPT_VISATTR *vis_attrs;
|
||||||
|
int *advances;
|
||||||
|
GOFFSET *offsets;
|
||||||
|
int max_clusters;
|
||||||
|
WORD *clusters;
|
||||||
} ME_Run;
|
} ME_Run;
|
||||||
|
|
||||||
typedef struct tagME_Border
|
typedef struct tagME_Border
|
||||||
|
@ -401,6 +412,7 @@ typedef struct tagME_TextEditor
|
||||||
SCROLLINFO vert_si, horz_si;
|
SCROLLINFO vert_si, horz_si;
|
||||||
|
|
||||||
BOOL bMouseCaptured;
|
BOOL bMouseCaptured;
|
||||||
|
int wheel_remain;
|
||||||
} ME_TextEditor;
|
} ME_TextEditor;
|
||||||
|
|
||||||
typedef struct tagME_Context
|
typedef struct tagME_Context
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit_lists);
|
||||||
|
@ -138,9 +139,24 @@ ME_DisplayItem *ME_FindItemFwd(ME_DisplayItem *di, ME_DIType nTypeOrClass)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *ME_GetDITypeName(ME_DIType type)
|
||||||
|
{
|
||||||
|
switch(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";
|
||||||
|
default: return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ME_DestroyDisplayItem(ME_DisplayItem *item)
|
void ME_DestroyDisplayItem(ME_DisplayItem *item)
|
||||||
{
|
{
|
||||||
/* TRACE("type=%s\n", ME_GetDITypeName(item->type)); */
|
if (0)
|
||||||
|
TRACE("type=%s\n", ME_GetDITypeName(item->type));
|
||||||
if (item->type==diParagraph)
|
if (item->type==diParagraph)
|
||||||
{
|
{
|
||||||
FREE_OBJ(item->member.para.pFmt);
|
FREE_OBJ(item->member.para.pFmt);
|
||||||
|
@ -150,6 +166,8 @@ void ME_DestroyDisplayItem(ME_DisplayItem *item)
|
||||||
if (item->type==diRun)
|
if (item->type==diRun)
|
||||||
{
|
{
|
||||||
if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj);
|
if (item->member.run.ole_obj) ME_DeleteReObject(item->member.run.ole_obj);
|
||||||
|
heap_free( item->member.run.glyphs );
|
||||||
|
heap_free( item->member.run.clusters );
|
||||||
ME_ReleaseStyle(item->member.run.style);
|
ME_ReleaseStyle(item->member.run.style);
|
||||||
}
|
}
|
||||||
FREE_OBJ(item);
|
FREE_OBJ(item);
|
||||||
|
@ -171,20 +189,6 @@ ME_DisplayItem *ME_MakeDI(ME_DIType type)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *ME_GetDITypeName(ME_DIType type)
|
|
||||||
{
|
|
||||||
switch(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";
|
|
||||||
default: return "?";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ME_DumpDocument(ME_TextBuffer *buffer)
|
void ME_DumpDocument(ME_TextBuffer *buffer)
|
||||||
{
|
{
|
||||||
/* FIXME this is useless, */
|
/* FIXME this is useless, */
|
||||||
|
|
|
@ -113,7 +113,7 @@ DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
|
||||||
|
|
|
@ -101,7 +101,7 @@ typedef HRESULT (WINAPI typeof(fnTextSrv_OnTxUIActivate))(ITextServices *iface);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_OnTxUIDeactivate))(ITextServices *iface);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_OnTxUIDeactivate))(ITextServices *iface);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetText))(ITextServices *iface,BSTR* pbstrText);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetText))(ITextServices *iface,BSTR* pbstrText);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxSetText))(ITextServices *iface,LPCWSTR pszText);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxSetText))(ITextServices *iface,LPCWSTR pszText);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetCurrentTargetX))(ITextServices *iface,LONG* x);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetCurTargetX))(ITextServices *iface,LONG* x);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetBaseLinePos))(ITextServices *iface,LONG* x);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetBaseLinePos))(ITextServices *iface,LONG* x);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetNaturalSize))(ITextServices *iface,DWORD dwAspect,HDC hdcDraw,HDC hicTargetDev,DVTARGETDEVICE* ptd,DWORD dwMode,const SIZEL* psizelExtent,LONG* pwidth,LONG* pheight);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetNaturalSize))(ITextServices *iface,DWORD dwAspect,HDC hdcDraw,HDC hicTargetDev,DVTARGETDEVICE* ptd,DWORD dwMode,const SIZEL* psizelExtent,LONG* pwidth,LONG* pheight);
|
||||||
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetDropTarget))(ITextServices *iface,struct IDropTarget** ppDropTarget);
|
typedef HRESULT (WINAPI typeof(fnTextSrv_TxGetDropTarget))(ITextServices *iface,struct IDropTarget** ppDropTarget);
|
||||||
|
|
|
@ -331,6 +331,11 @@ static void draw_text( ME_Context *c, ME_Run *run, int x, int y, BOOL selected,
|
||||||
old_text = SetTextColor( c->hDC, text_color );
|
old_text = SetTextColor( c->hDC, text_color );
|
||||||
if (selected) old_back = SetBkColor( c->hDC, back_color );
|
if (selected) old_back = SetBkColor( c->hDC, back_color );
|
||||||
|
|
||||||
|
if (run->para->nFlags & MEPF_COMPLEX)
|
||||||
|
ScriptTextOut( c->hDC, &run->style->script_cache, x, y, selected ? ETO_OPAQUE : 0, sel_rect,
|
||||||
|
&run->script_analysis, NULL, 0, run->glyphs, run->num_glyphs, run->advances,
|
||||||
|
NULL, run->offsets );
|
||||||
|
else
|
||||||
ExtTextOutW( c->hDC, x, y, selected ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL );
|
ExtTextOutW( c->hDC, x, y, selected ? ETO_OPAQUE : 0, sel_rect, text, run->len, NULL );
|
||||||
|
|
||||||
if (selected) SetBkColor( c->hDC, old_back );
|
if (selected) SetBkColor( c->hDC, old_back );
|
||||||
|
|
|
@ -41,8 +41,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
|
|
||||||
extern HANDLE me_heap;
|
|
||||||
|
|
||||||
static int _RTFGetChar(RTF_Info *);
|
static int _RTFGetChar(RTF_Info *);
|
||||||
static void _RTFGetToken (RTF_Info *);
|
static void _RTFGetToken (RTF_Info *);
|
||||||
static void _RTFGetToken2 (RTF_Info *);
|
static void _RTFGetToken2 (RTF_Info *);
|
||||||
|
@ -247,7 +245,7 @@ void RTFInit(RTF_Info *info)
|
||||||
info->rtfLineNum = 0;
|
info->rtfLineNum = 0;
|
||||||
info->rtfLinePos = 0;
|
info->rtfLinePos = 0;
|
||||||
info->prevChar = EOF;
|
info->prevChar = EOF;
|
||||||
info->bumpLine = 0;
|
info->bumpLine = FALSE;
|
||||||
|
|
||||||
info->dwCPOutputCount = 0;
|
info->dwCPOutputCount = 0;
|
||||||
if (!info->cpOutputBuffer)
|
if (!info->cpOutputBuffer)
|
||||||
|
@ -713,7 +711,7 @@ static void _RTFGetToken2(RTF_Info *info)
|
||||||
static int GetChar(RTF_Info *info)
|
static int GetChar(RTF_Info *info)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
int oldBumpLine;
|
BOOL oldBumpLine;
|
||||||
|
|
||||||
if ((c = _RTFGetChar(info)) != EOF)
|
if ((c = _RTFGetChar(info)) != EOF)
|
||||||
{
|
{
|
||||||
|
@ -721,16 +719,16 @@ static int GetChar(RTF_Info *info)
|
||||||
info->rtfTextBuf[info->rtfTextLen] = '\0';
|
info->rtfTextBuf[info->rtfTextLen] = '\0';
|
||||||
}
|
}
|
||||||
if (info->prevChar == EOF)
|
if (info->prevChar == EOF)
|
||||||
info->bumpLine = 1;
|
info->bumpLine = TRUE;
|
||||||
oldBumpLine = info->bumpLine; /* non-zero if prev char was line ending */
|
oldBumpLine = info->bumpLine; /* TRUE if prev char was line ending */
|
||||||
info->bumpLine = 0;
|
info->bumpLine = FALSE;
|
||||||
if (c == '\r')
|
if (c == '\r')
|
||||||
info->bumpLine = 1;
|
info->bumpLine = TRUE;
|
||||||
else if (c == '\n')
|
else if (c == '\n')
|
||||||
{
|
{
|
||||||
info->bumpLine = 1;
|
info->bumpLine = TRUE;
|
||||||
if (info->prevChar == '\r') /* oops, previous \r wasn't */
|
if (info->prevChar == '\r') /* oops, previous \r wasn't */
|
||||||
oldBumpLine = 0; /* really a line ending */
|
oldBumpLine = FALSE; /* really a line ending */
|
||||||
}
|
}
|
||||||
++info->rtfLinePos;
|
++info->rtfLinePos;
|
||||||
if (oldBumpLine) /* were we supposed to increment the */
|
if (oldBumpLine) /* were we supposed to increment the */
|
||||||
|
|
|
@ -503,6 +503,9 @@ ITextDocument_fnGetSelection(ITextDocument* me, ITextSelection** ppSel)
|
||||||
{
|
{
|
||||||
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
IRichEditOleImpl *This = impl_from_ITextDocument(me);
|
||||||
TRACE("(%p)\n", me);
|
TRACE("(%p)\n", me);
|
||||||
|
|
||||||
|
if(!ppSel)
|
||||||
|
return E_INVALIDARG;
|
||||||
*ppSel = &This->txtSel->ITextSelection_iface;
|
*ppSel = &This->txtSel->ITextSelection_iface;
|
||||||
ITextSelection_AddRef(*ppSel);
|
ITextSelection_AddRef(*ppSel);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
@ -1502,7 +1505,7 @@ LRESULT CreateIRichEditOle(ME_TextEditor *editor, LPVOID *ppObj)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
reo->clientSite = CreateOleClientSite(reo);
|
reo->clientSite = CreateOleClientSite(reo);
|
||||||
if (!reo->txtSel)
|
if (!reo->clientSite)
|
||||||
{
|
{
|
||||||
ITextSelection_Release(&reo->txtSel->ITextSelection_iface);
|
ITextSelection_Release(&reo->txtSel->ITextSelection_iface);
|
||||||
heap_free(reo);
|
heap_free(reo);
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
/* I'm sure these functions would simplify some code in caret ops etc,
|
/* I'm sure these functions would simplify some code in caret ops etc,
|
||||||
|
|
|
@ -1129,7 +1129,7 @@ struct _RTF_Info {
|
||||||
char *pushedTextBuf;
|
char *pushedTextBuf;
|
||||||
|
|
||||||
int prevChar;
|
int prevChar;
|
||||||
int bumpLine;
|
BOOL bumpLine;
|
||||||
|
|
||||||
/* Document-wide attributes */
|
/* Document-wide attributes */
|
||||||
RTFFont *fontList; /* these lists MUST be */
|
RTFFont *fontList; /* these lists MUST be */
|
||||||
|
|
|
@ -30,17 +30,17 @@ WINE_DECLARE_DEBUG_CHANNEL(richedit_lists);
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* ME_CanJoinRuns
|
* ME_CanJoinRuns
|
||||||
*
|
*
|
||||||
* Returns 1 if two runs can be safely merged into one, 0 otherwise.
|
* Returns TRUE if two runs can be safely merged into one, FALSE otherwise.
|
||||||
*/
|
*/
|
||||||
int ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
|
BOOL ME_CanJoinRuns(const ME_Run *run1, const ME_Run *run2)
|
||||||
{
|
{
|
||||||
if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN)
|
if ((run1->nFlags | run2->nFlags) & MERF_NOJOIN)
|
||||||
return 0;
|
return FALSE;
|
||||||
if (run1->style != run2->style)
|
if (run1->style != run2->style)
|
||||||
return 0;
|
return FALSE;
|
||||||
if ((run1->nFlags & MERF_STYLEFLAGS) != (run2->nFlags & MERF_STYLEFLAGS))
|
if ((run1->nFlags & MERF_STYLEFLAGS) != (run2->nFlags & MERF_STYLEFLAGS))
|
||||||
return 0;
|
return FALSE;
|
||||||
return 1;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift)
|
void ME_SkipAndPropagateCharOffset(ME_DisplayItem *p, int shift)
|
||||||
|
@ -295,6 +295,14 @@ ME_DisplayItem *ME_MakeRun(ME_Style *s, int nFlags)
|
||||||
item->member.run.nCharOfs = -1;
|
item->member.run.nCharOfs = -1;
|
||||||
item->member.run.len = 0;
|
item->member.run.len = 0;
|
||||||
item->member.run.para = NULL;
|
item->member.run.para = NULL;
|
||||||
|
item->member.run.num_glyphs = 0;
|
||||||
|
item->member.run.max_glyphs = 0;
|
||||||
|
item->member.run.glyphs = NULL;
|
||||||
|
item->member.run.vis_attrs = NULL;
|
||||||
|
item->member.run.advances = NULL;
|
||||||
|
item->member.run.offsets = NULL;
|
||||||
|
item->member.run.max_clusters = 0;
|
||||||
|
item->member.run.clusters = NULL;
|
||||||
ME_AddRefStyle(s);
|
ME_AddRefStyle(s);
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -310,23 +318,52 @@ ME_DisplayItem *
|
||||||
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
|
ME_InsertRunAtCursor(ME_TextEditor *editor, ME_Cursor *cursor, ME_Style *style,
|
||||||
const WCHAR *str, int len, int flags)
|
const WCHAR *str, int len, int flags)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *pDI;
|
ME_DisplayItem *pDI, *insert_before = cursor->pRun, *prev;
|
||||||
|
|
||||||
if (cursor->nOffset)
|
if (cursor->nOffset)
|
||||||
ME_SplitRunSimple(editor, cursor);
|
{
|
||||||
|
if (cursor->nOffset == cursor->pRun->member.run.len)
|
||||||
|
{
|
||||||
|
insert_before = ME_FindItemFwd( cursor->pRun, diRun );
|
||||||
|
if (!insert_before) insert_before = cursor->pRun; /* Always insert before the final eop run */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ME_SplitRunSimple( editor, cursor );
|
||||||
|
insert_before = cursor->pRun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
add_undo_delete_run( editor, cursor->pPara->member.para.nCharOfs +
|
add_undo_delete_run( editor, insert_before->member.run.para->nCharOfs +
|
||||||
cursor->pRun->member.run.nCharOfs, len );
|
insert_before->member.run.nCharOfs, len );
|
||||||
|
|
||||||
pDI = ME_MakeRun(style, flags);
|
pDI = ME_MakeRun(style, flags);
|
||||||
pDI->member.run.nCharOfs = cursor->pRun->member.run.nCharOfs;
|
pDI->member.run.nCharOfs = insert_before->member.run.nCharOfs;
|
||||||
pDI->member.run.len = len;
|
pDI->member.run.len = len;
|
||||||
pDI->member.run.para = cursor->pRun->member.run.para;
|
pDI->member.run.para = insert_before->member.run.para;
|
||||||
ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len );
|
ME_InsertString( pDI->member.run.para->text, pDI->member.run.nCharOfs, str, len );
|
||||||
ME_InsertBefore(cursor->pRun, pDI);
|
ME_InsertBefore( insert_before, pDI );
|
||||||
TRACE("Shift length:%d\n", len);
|
TRACE("Shift length:%d\n", len);
|
||||||
ME_PropagateCharOffset(cursor->pRun, len);
|
ME_PropagateCharOffset( insert_before, len );
|
||||||
cursor->pPara->member.para.nFlags |= MEPF_REWRAP;
|
insert_before->member.run.para->nFlags |= MEPF_REWRAP;
|
||||||
|
|
||||||
|
/* Move any cursors that were at the end of the previous run to the end of the inserted run */
|
||||||
|
prev = ME_FindItemBack( pDI, diRun );
|
||||||
|
if (prev)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < editor->nCursors; i++)
|
||||||
|
{
|
||||||
|
if (editor->pCursors[i].pRun == prev &&
|
||||||
|
editor->pCursors[i].nOffset == prev->member.run.len)
|
||||||
|
{
|
||||||
|
editor->pCursors[i].pRun = pDI;
|
||||||
|
editor->pCursors[i].nOffset = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return pDI;
|
return pDI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,6 +476,18 @@ int ME_CharFromPointContext(ME_Context *c, int cx, ME_Run *run, BOOL closest, BO
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (run->para->nFlags & MEPF_COMPLEX)
|
||||||
|
{
|
||||||
|
int cp, trailing;
|
||||||
|
if (visual_order && run->script_analysis.fRTL) cx = run->nWidth - cx - 1;
|
||||||
|
|
||||||
|
ScriptXtoCP( cx, run->len, run->num_glyphs, run->clusters, run->vis_attrs, run->advances, &run->script_analysis,
|
||||||
|
&cp, &trailing );
|
||||||
|
TRACE("x %d cp %d trailing %d (run width %d) rtl %d log order %d\n", cx, cp, trailing, run->nWidth,
|
||||||
|
run->script_analysis.fRTL, run->script_analysis.fLogicalOrder);
|
||||||
|
return closest ? cp + trailing : cp;
|
||||||
|
}
|
||||||
|
|
||||||
if (c->editor->cPasswordMask)
|
if (c->editor->cPasswordMask)
|
||||||
{
|
{
|
||||||
mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len );
|
mask_text = ME_MakeStringR( c->editor->cPasswordMask, run->len );
|
||||||
|
@ -514,6 +563,14 @@ int ME_PointFromCharContext(ME_Context *c, ME_Run *pRun, int nOffset, BOOL visua
|
||||||
nOffset = 0;
|
nOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pRun->para->nFlags & MEPF_COMPLEX)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
ScriptCPtoX( nOffset, FALSE, pRun->len, pRun->num_glyphs, pRun->clusters,
|
||||||
|
pRun->vis_attrs, pRun->advances, &pRun->script_analysis, &x );
|
||||||
|
if (visual_order && pRun->script_analysis.fRTL) x = pRun->nWidth - x - 1;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
if (c->editor->cPasswordMask)
|
if (c->editor->cPasswordMask)
|
||||||
{
|
{
|
||||||
mask_text = ME_MakeStringR(c->editor->cPasswordMask, pRun->len);
|
mask_text = ME_MakeStringR(c->editor->cPasswordMask, pRun->len);
|
||||||
|
@ -564,7 +621,11 @@ SIZE ME_GetRunSizeCommon(ME_Context *c, const ME_Paragraph *para, ME_Run *run, i
|
||||||
* in practice
|
* in practice
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (c->editor->cPasswordMask)
|
if (para->nFlags & MEPF_COMPLEX)
|
||||||
|
{
|
||||||
|
size.cx = run->nWidth;
|
||||||
|
}
|
||||||
|
else if (c->editor->cPasswordMask)
|
||||||
{
|
{
|
||||||
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen);
|
ME_String *szMasked = ME_MakeStringR(c->editor->cPasswordMask,nLen);
|
||||||
ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
|
ME_GetTextExtent(c, szMasked->szData, nLen,run->style, &size);
|
||||||
|
@ -658,19 +719,20 @@ void ME_SetSelectionCharFormat(ME_TextEditor *editor, CHARFORMAT2W *pFmt)
|
||||||
*/
|
*/
|
||||||
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt)
|
void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, CHARFORMAT2W *pFmt)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *para;
|
ME_DisplayItem *run, *start_run = start->pRun, *end_run = NULL;
|
||||||
ME_DisplayItem *run;
|
|
||||||
ME_DisplayItem *end_run = NULL;
|
|
||||||
|
|
||||||
if (end && start->pRun == end->pRun && start->nOffset == end->nOffset)
|
if (end && start->pRun == end->pRun && start->nOffset == end->nOffset)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (start->nOffset)
|
if (start->nOffset == start->pRun->member.run.len)
|
||||||
|
start_run = ME_FindItemFwd( start->pRun, diRun );
|
||||||
|
else if (start->nOffset)
|
||||||
{
|
{
|
||||||
/* SplitRunSimple may or may not update the cursors, depending on whether they
|
/* SplitRunSimple may or may not update the cursors, depending on whether they
|
||||||
* are selection cursors, but we need to make sure they are valid. */
|
* are selection cursors, but we need to make sure they are valid. */
|
||||||
int split_offset = start->nOffset;
|
int split_offset = start->nOffset;
|
||||||
ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start);
|
ME_DisplayItem *split_run = ME_SplitRunSimple(editor, start);
|
||||||
|
start_run = start->pRun;
|
||||||
if (end && end->pRun == split_run)
|
if (end && end->pRun == split_run)
|
||||||
{
|
{
|
||||||
end->pRun = start->pRun;
|
end->pRun = start->pRun;
|
||||||
|
@ -678,31 +740,26 @@ void ME_SetCharFormat(ME_TextEditor *editor, ME_Cursor *start, ME_Cursor *end, C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end && end->nOffset)
|
if (end)
|
||||||
ME_SplitRunSimple(editor, end);
|
{
|
||||||
end_run = end ? end->pRun : NULL;
|
if (end->nOffset == end->pRun->member.run.len)
|
||||||
|
end_run = ME_FindItemFwd( end->pRun, diRun );
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (end->nOffset) ME_SplitRunSimple(editor, end);
|
||||||
|
end_run = end->pRun;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
run = start->pRun;
|
for (run = start_run; run != end_run; run = ME_FindItemFwd( run, diRun ))
|
||||||
para = start->pPara;
|
|
||||||
para->member.para.nFlags |= MEPF_REWRAP;
|
|
||||||
|
|
||||||
while(run != end_run)
|
|
||||||
{
|
{
|
||||||
ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt);
|
ME_Style *new_style = ME_ApplyStyle(run->member.run.style, pFmt);
|
||||||
/* ME_DumpStyle(new_style); */
|
|
||||||
|
|
||||||
add_undo_set_char_fmt( editor, para->member.para.nCharOfs + run->member.run.nCharOfs,
|
add_undo_set_char_fmt( editor, run->member.run.para->nCharOfs + run->member.run.nCharOfs,
|
||||||
run->member.run.len, &run->member.run.style->fmt );
|
run->member.run.len, &run->member.run.style->fmt );
|
||||||
ME_ReleaseStyle(run->member.run.style);
|
ME_ReleaseStyle(run->member.run.style);
|
||||||
run->member.run.style = new_style;
|
run->member.run.style = new_style;
|
||||||
run = ME_FindItemFwd(run, diRunOrParagraph);
|
run->member.run.para->nFlags |= MEPF_REWRAP;
|
||||||
if (run && run->type == diParagraph)
|
|
||||||
{
|
|
||||||
para = run;
|
|
||||||
run = ME_FindItemFwd(run, diRun);
|
|
||||||
if (run != end_run)
|
|
||||||
para->member.para.nFlags |= MEPF_REWRAP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -172,23 +172,30 @@ ME_CallWordBreakProc(ME_TextEditor *editor, WCHAR *str, INT len, INT start, INT
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LPWSTR ME_ToUnicode(BOOL unicode, LPVOID psz)
|
LPWSTR ME_ToUnicode(LONG codepage, LPVOID psz, INT *len)
|
||||||
{
|
{
|
||||||
assert(psz != NULL);
|
*len = 0;
|
||||||
|
if (!psz) return NULL;
|
||||||
|
|
||||||
if (unicode)
|
if (codepage == CP_UNICODE)
|
||||||
|
{
|
||||||
|
*len = lstrlenW(psz);
|
||||||
return psz;
|
return psz;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
WCHAR *tmp;
|
WCHAR *tmp;
|
||||||
int nChars = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
|
int nChars = MultiByteToWideChar(codepage, 0, psz, -1, NULL, 0);
|
||||||
|
|
||||||
|
if(!nChars) return NULL;
|
||||||
|
|
||||||
if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
|
if((tmp = ALLOC_N_OBJ(WCHAR, nChars)) != NULL)
|
||||||
MultiByteToWideChar(CP_ACP, 0, psz, -1, tmp, nChars);
|
*len = MultiByteToWideChar(codepage, 0, psz, -1, tmp, nChars) - 1;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ME_EndToUnicode(BOOL unicode, LPVOID psz)
|
void ME_EndToUnicode(LONG codepage, LPVOID psz)
|
||||||
{
|
{
|
||||||
if (!unicode)
|
if (codepage != CP_UNICODE)
|
||||||
FREE_OBJ(psz);
|
FREE_OBJ(psz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,6 +149,7 @@ ME_Style *ME_MakeStyle(CHARFORMAT2W *style)
|
||||||
s->hFont = NULL;
|
s->hFont = NULL;
|
||||||
memset(&s->tm, 0, sizeof(s->tm));
|
memset(&s->tm, 0, sizeof(s->tm));
|
||||||
s->tm.tmAscent = -1;
|
s->tm.tmAscent = -1;
|
||||||
|
s->script_cache = NULL;
|
||||||
all_refs++;
|
all_refs++;
|
||||||
TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs);
|
TRACE_(richedit_style)("ME_MakeStyle %p, total refs=%d\n", s, all_refs);
|
||||||
return s;
|
return s;
|
||||||
|
@ -435,6 +436,7 @@ static void ME_DestroyStyle(ME_Style *s) {
|
||||||
DeleteObject(s->hFont);
|
DeleteObject(s->hFont);
|
||||||
s->hFont = NULL;
|
s->hFont = NULL;
|
||||||
}
|
}
|
||||||
|
ScriptFreeCache( &s->script_cache );
|
||||||
FREE_OBJ(s);
|
FREE_OBJ(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
*
|
*
|
||||||
* Richedit version 4.1:
|
* Richedit version 4.1:
|
||||||
* Tables are implemented such that cells can contain multiple paragraphs,
|
* Tables are implemented such that cells can contain multiple paragraphs,
|
||||||
* each with it's own paragraph format, and cells may even contain tables
|
* each with its own paragraph format, and cells may even contain tables
|
||||||
* nested within the cell.
|
* nested within the cell.
|
||||||
*
|
*
|
||||||
* There is also a paragraph at the start of each table row that contains
|
* There is also a paragraph at the start of each table row that contains
|
||||||
|
|
|
@ -278,7 +278,7 @@ DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurrentTargetX(ITextServices *iface, LONG *x)
|
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxGetCurTargetX(ITextServices *iface, LONG *x)
|
||||||
{
|
{
|
||||||
ITextServicesImpl *This = impl_from_ITextServices(iface);
|
ITextServicesImpl *This = impl_from_ITextServices(iface);
|
||||||
|
|
||||||
|
@ -340,7 +340,7 @@ DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIActivate,4)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_OnTxUIDeactivate,4)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetText,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxSetText,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurrentTargetX,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetCurTargetX,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetBaseLinePos,8)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetNaturalSize,36)
|
||||||
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
|
DEFINE_THISCALL_WRAPPER(fnTextSrv_TxGetDropTarget,8)
|
||||||
|
@ -364,7 +364,7 @@ static const ITextServicesVtbl textservices_vtbl =
|
||||||
THISCALL(fnTextSrv_OnTxUIDeactivate),
|
THISCALL(fnTextSrv_OnTxUIDeactivate),
|
||||||
THISCALL(fnTextSrv_TxGetText),
|
THISCALL(fnTextSrv_TxGetText),
|
||||||
THISCALL(fnTextSrv_TxSetText),
|
THISCALL(fnTextSrv_TxSetText),
|
||||||
THISCALL(fnTextSrv_TxGetCurrentTargetX),
|
THISCALL(fnTextSrv_TxGetCurTargetX),
|
||||||
THISCALL(fnTextSrv_TxGetBaseLinePos),
|
THISCALL(fnTextSrv_TxGetBaseLinePos),
|
||||||
THISCALL(fnTextSrv_TxGetNaturalSize),
|
THISCALL(fnTextSrv_TxGetNaturalSize),
|
||||||
THISCALL(fnTextSrv_TxGetDropTarget),
|
THISCALL(fnTextSrv_TxGetDropTarget),
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "editor.h"
|
#include "editor.h"
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
|
@ -31,6 +32,66 @@ WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
* - no tabs
|
* - no tabs
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static BOOL get_run_glyph_buffers( ME_Run *run )
|
||||||
|
{
|
||||||
|
heap_free( run->glyphs );
|
||||||
|
run->glyphs = heap_alloc( run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int) + sizeof(GOFFSET)) );
|
||||||
|
if (!run->glyphs) return FALSE;
|
||||||
|
|
||||||
|
run->vis_attrs = (SCRIPT_VISATTR*)((char*)run->glyphs + run->max_glyphs * sizeof(WORD));
|
||||||
|
run->advances = (int*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR)));
|
||||||
|
run->offsets = (GOFFSET*)((char*)run->glyphs + run->max_glyphs * (sizeof(WORD) + sizeof(SCRIPT_VISATTR) + sizeof(int)));
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT shape_run( ME_Context *c, ME_Run *run )
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
HFONT old_font;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!run->glyphs)
|
||||||
|
{
|
||||||
|
run->max_glyphs = 1.5 * run->len + 16; /* This is suggested in the uniscribe documentation */
|
||||||
|
run->max_glyphs = (run->max_glyphs + 7) & ~7; /* Keep alignment simple */
|
||||||
|
get_run_glyph_buffers( run );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (run->max_clusters < run->len)
|
||||||
|
{
|
||||||
|
heap_free( run->clusters );
|
||||||
|
run->max_clusters = run->len * 2;
|
||||||
|
run->clusters = heap_alloc( run->max_clusters * sizeof(WORD) );
|
||||||
|
}
|
||||||
|
|
||||||
|
old_font = ME_SelectStyleFont( c, run->style );
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
hr = ScriptShape( c->hDC, &run->style->script_cache, get_text( run, 0 ), run->len, run->max_glyphs,
|
||||||
|
&run->script_analysis, run->glyphs, run->clusters, run->vis_attrs, &run->num_glyphs );
|
||||||
|
if (hr != E_OUTOFMEMORY) break;
|
||||||
|
if (run->max_glyphs > 10 * run->len) break; /* something has clearly gone wrong */
|
||||||
|
run->max_glyphs *= 2;
|
||||||
|
get_run_glyph_buffers( run );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
hr = ScriptPlace( c->hDC, &run->style->script_cache, run->glyphs, run->num_glyphs, run->vis_attrs,
|
||||||
|
&run->script_analysis, run->advances, run->offsets, NULL );
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
for (i = 0, run->nWidth = 0; i < run->num_glyphs; i++)
|
||||||
|
run->nWidth += run->advances[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ME_UnselectStyleFont( c, run->style, old_font );
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* calc_run_extent
|
* calc_run_extent
|
||||||
*
|
*
|
||||||
|
@ -77,7 +138,10 @@ static ME_DisplayItem *split_run_extents(ME_WrapContext *wc, ME_DisplayItem *ite
|
||||||
ME_SplitRunSimple(editor, &cursor);
|
ME_SplitRunSimple(editor, &cursor);
|
||||||
|
|
||||||
run2 = &cursor.pRun->member.run;
|
run2 = &cursor.pRun->member.run;
|
||||||
|
run2->script_analysis = run->script_analysis;
|
||||||
|
|
||||||
|
shape_run( wc->context, run );
|
||||||
|
shape_run( wc->context, run2 );
|
||||||
calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run);
|
calc_run_extent(wc->context, para, wc->nRow ? wc->nLeftMargin : wc->nFirstMargin, run);
|
||||||
|
|
||||||
run2->pt.x = run->pt.x+run->nWidth;
|
run2->pt.x = run->pt.x+run->nWidth;
|
||||||
|
@ -165,15 +229,73 @@ static void ME_BeginRow(ME_WrapContext *wc)
|
||||||
wc->pt.y++;
|
wc->pt.y++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void layout_row( ME_DisplayItem *start, const ME_DisplayItem *end )
|
||||||
|
{
|
||||||
|
ME_DisplayItem *p;
|
||||||
|
int i, num_runs = 0;
|
||||||
|
int buf[16 * 5]; /* 5 arrays - 4 of int & 1 of BYTE, alloc space for 5 of ints */
|
||||||
|
int *vis_to_log = buf, *log_to_vis, *widths, *pos;
|
||||||
|
BYTE *levels;
|
||||||
|
BOOL found_black = FALSE;
|
||||||
|
|
||||||
|
for (p = end->prev; p != start->prev; p = p->prev)
|
||||||
|
{
|
||||||
|
if (p->type == diRun)
|
||||||
|
{
|
||||||
|
if (!found_black) found_black = !(p->member.run.nFlags & (MERF_WHITESPACE | MERF_ENDPARA));
|
||||||
|
if (found_black) num_runs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE("%d runs\n", num_runs);
|
||||||
|
if (!num_runs) return;
|
||||||
|
|
||||||
|
if (num_runs > sizeof(buf) / (sizeof(buf[0]) * 5))
|
||||||
|
vis_to_log = heap_alloc( num_runs * sizeof(int) * 5 );
|
||||||
|
|
||||||
|
log_to_vis = vis_to_log + num_runs;
|
||||||
|
widths = vis_to_log + 2 * num_runs;
|
||||||
|
pos = vis_to_log + 3 * num_runs;
|
||||||
|
levels = (BYTE*)(vis_to_log + 4 * num_runs);
|
||||||
|
|
||||||
|
for (i = 0, p = start; i < num_runs; p = p->next)
|
||||||
|
{
|
||||||
|
if (p->type == diRun)
|
||||||
|
{
|
||||||
|
levels[i] = p->member.run.script_analysis.s.uBidiLevel;
|
||||||
|
widths[i] = p->member.run.nWidth;
|
||||||
|
TRACE( "%d: level %d width %d\n", i, levels[i], widths[i] );
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptLayout( num_runs, levels, vis_to_log, log_to_vis );
|
||||||
|
|
||||||
|
pos[0] = start->member.run.para->pt.x;
|
||||||
|
for (i = 1; i < num_runs; i++)
|
||||||
|
pos[i] = pos[i - 1] + widths[ vis_to_log[ i - 1 ] ];
|
||||||
|
|
||||||
|
for (i = 0, p = start; i < num_runs; p = p->next)
|
||||||
|
{
|
||||||
|
if (p->type == diRun)
|
||||||
|
{
|
||||||
|
p->member.run.pt.x = pos[ log_to_vis[ i ] ];
|
||||||
|
TRACE( "%d: x = %d\n", i, p->member.run.pt.x );
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vis_to_log != buf) heap_free( vis_to_log );
|
||||||
|
}
|
||||||
|
|
||||||
static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
||||||
{
|
{
|
||||||
ME_DisplayItem *p, *row, *para;
|
ME_DisplayItem *p, *row;
|
||||||
|
ME_Paragraph *para = &wc->pPara->member.para;
|
||||||
BOOL bSkippingSpaces = TRUE;
|
BOOL bSkippingSpaces = TRUE;
|
||||||
int ascent = 0, descent = 0, width=0, shift = 0, align = 0;
|
int ascent = 0, descent = 0, width=0, shift = 0, align = 0;
|
||||||
PARAFORMAT2 *pFmt;
|
|
||||||
/* wrap text */
|
/* wrap text */
|
||||||
para = wc->pPara;
|
|
||||||
pFmt = para->member.para.pFmt;
|
|
||||||
|
|
||||||
for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
|
for (p = pEnd->prev; p!=wc->pRowStart->prev; p = p->prev)
|
||||||
{
|
{
|
||||||
|
@ -207,10 +329,10 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
para->member.para.nWidth = max(para->member.para.nWidth, width);
|
para->nWidth = max(para->nWidth, width);
|
||||||
row = ME_MakeRow(ascent+descent, ascent, width);
|
row = ME_MakeRow(ascent+descent, ascent, width);
|
||||||
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
if (wc->context->editor->bEmulateVersion10 && /* v1.0 - 3.0 */
|
||||||
pFmt->dwMask & PFM_TABLE && pFmt->wEffects & PFE_TABLE)
|
(para->pFmt->dwMask & PFM_TABLE) && (para->pFmt->wEffects & PFE_TABLE))
|
||||||
{
|
{
|
||||||
/* The text was shifted down in ME_BeginRow so move the wrap context
|
/* The text was shifted down in ME_BeginRow so move the wrap context
|
||||||
* back to where it should be. */
|
* back to where it should be. */
|
||||||
|
@ -221,12 +343,15 @@ static void ME_InsertRowStart(ME_WrapContext *wc, const ME_DisplayItem *pEnd)
|
||||||
row->member.row.pt = wc->pt;
|
row->member.row.pt = wc->pt;
|
||||||
row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
|
row->member.row.nLMargin = (!wc->nRow ? wc->nFirstMargin : wc->nLeftMargin);
|
||||||
row->member.row.nRMargin = wc->nRightMargin;
|
row->member.row.nRMargin = wc->nRightMargin;
|
||||||
assert(para->member.para.pFmt->dwMask & PFM_ALIGNMENT);
|
assert(para->pFmt->dwMask & PFM_ALIGNMENT);
|
||||||
align = para->member.para.pFmt->wAlignment;
|
align = para->pFmt->wAlignment;
|
||||||
if (align == PFA_CENTER)
|
if (align == PFA_CENTER)
|
||||||
shift = max((wc->nAvailWidth-width)/2, 0);
|
shift = max((wc->nAvailWidth-width)/2, 0);
|
||||||
if (align == PFA_RIGHT)
|
if (align == PFA_RIGHT)
|
||||||
shift = max(wc->nAvailWidth-width, 0);
|
shift = max(wc->nAvailWidth-width, 0);
|
||||||
|
|
||||||
|
if (para->nFlags & MEPF_COMPLEX) layout_row( wc->pRowStart, pEnd );
|
||||||
|
|
||||||
row->member.row.pt.x = row->member.row.nLMargin + shift;
|
row->member.row.pt.x = row->member.row.nLMargin + shift;
|
||||||
for (p = wc->pRowStart; p!=pEnd; p = p->next)
|
for (p = wc->pRowStart; p!=pEnd; p = p->next)
|
||||||
{
|
{
|
||||||
|
@ -613,6 +738,111 @@ static void ME_PrepareParagraphForWrapping(ME_Context *c, ME_DisplayItem *tp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT itemize_para( ME_Context *c, ME_DisplayItem *p )
|
||||||
|
{
|
||||||
|
ME_Paragraph *para = &p->member.para;
|
||||||
|
ME_Run *run;
|
||||||
|
ME_DisplayItem *di;
|
||||||
|
SCRIPT_ITEM buf[16], *items = buf;
|
||||||
|
int items_passed = sizeof( buf ) / sizeof( buf[0] ), num_items, cur_item;
|
||||||
|
SCRIPT_CONTROL control = { LANG_USER_DEFAULT, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
|
||||||
|
FALSE, FALSE, 0 };
|
||||||
|
SCRIPT_STATE state = { 0, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, 0, 0 };
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
assert( p->type == diParagraph );
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
hr = ScriptItemize( para->text->szData, para->text->nLen, items_passed, &control,
|
||||||
|
&state, items, &num_items );
|
||||||
|
if (hr != E_OUTOFMEMORY) break; /* may not be enough items if hr == E_OUTOFMEMORY */
|
||||||
|
if (items_passed > para->text->nLen + 1) break; /* something else has gone wrong */
|
||||||
|
items_passed *= 2;
|
||||||
|
if (items == buf)
|
||||||
|
items = heap_alloc( items_passed * sizeof( *items ) );
|
||||||
|
else
|
||||||
|
items = heap_realloc( items, items_passed * sizeof( *items ) );
|
||||||
|
if (!items) break;
|
||||||
|
}
|
||||||
|
if (FAILED( hr )) goto end;
|
||||||
|
|
||||||
|
if (TRACE_ON( richedit ))
|
||||||
|
{
|
||||||
|
TRACE( "got items:\n" );
|
||||||
|
for (cur_item = 0; cur_item < num_items; cur_item++)
|
||||||
|
{
|
||||||
|
TRACE( "\t%d - %d RTL %d bidi level %d\n", items[cur_item].iCharPos, items[cur_item+1].iCharPos - 1,
|
||||||
|
items[cur_item].a.fRTL, items[cur_item].a.s.uBidiLevel );
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE( "before splitting runs into ranges\n" );
|
||||||
|
for (di = p->next; di != p->member.para.next_para; di = di->next)
|
||||||
|
{
|
||||||
|
if (di->type != diRun) continue;
|
||||||
|
TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split runs into ranges at item boundaries */
|
||||||
|
for (di = p->next, cur_item = 0; di != p->member.para.next_para; di = di->next)
|
||||||
|
{
|
||||||
|
if (di->type != diRun) continue;
|
||||||
|
run = &di->member.run;
|
||||||
|
|
||||||
|
if (run->nCharOfs == items[cur_item+1].iCharPos) cur_item++;
|
||||||
|
|
||||||
|
items[cur_item].a.fLogicalOrder = TRUE;
|
||||||
|
run->script_analysis = items[cur_item].a;
|
||||||
|
|
||||||
|
if (run->nFlags & MERF_ENDPARA) break; /* don't split eop runs */
|
||||||
|
|
||||||
|
if (run->nCharOfs + run->len > items[cur_item+1].iCharPos)
|
||||||
|
{
|
||||||
|
ME_Cursor cursor = {p, di, items[cur_item+1].iCharPos - run->nCharOfs};
|
||||||
|
ME_SplitRunSimple( c->editor, &cursor );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TRACE_ON( richedit ))
|
||||||
|
{
|
||||||
|
TRACE( "after splitting into ranges\n" );
|
||||||
|
for (di = p->next; di != p->member.para.next_para; di = di->next)
|
||||||
|
{
|
||||||
|
if (di->type != diRun) continue;
|
||||||
|
TRACE( "\t%d: %s\n", di->member.run.nCharOfs, debugstr_run( &di->member.run ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
para->nFlags |= MEPF_COMPLEX;
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (items != buf) heap_free( items );
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static HRESULT shape_para( ME_Context *c, ME_DisplayItem *p )
|
||||||
|
{
|
||||||
|
ME_DisplayItem *di;
|
||||||
|
ME_Run *run;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
for (di = p->next; di != p->member.para.next_para; di = di->next)
|
||||||
|
{
|
||||||
|
if (di->type != diRun) continue;
|
||||||
|
run = &di->member.run;
|
||||||
|
|
||||||
|
hr = shape_run( c, run );
|
||||||
|
if (FAILED( hr ))
|
||||||
|
{
|
||||||
|
run->para->nFlags &= ~MEPF_COMPLEX;
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
||||||
ME_DisplayItem *p;
|
ME_DisplayItem *p;
|
||||||
ME_WrapContext wc;
|
ME_WrapContext wc;
|
||||||
|
@ -625,6 +855,15 @@ static void ME_WrapTextParagraph(ME_Context *c, ME_DisplayItem *tp) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ME_PrepareParagraphForWrapping(c, tp);
|
ME_PrepareParagraphForWrapping(c, tp);
|
||||||
|
|
||||||
|
/* For now treating all non-password text as complex for better testing */
|
||||||
|
if (!c->editor->cPasswordMask /* &&
|
||||||
|
ScriptIsComplex( tp->member.para.text->szData, tp->member.para.text->nLen, SIC_COMPLEX ) == S_OK */)
|
||||||
|
{
|
||||||
|
if (SUCCEEDED( itemize_para( c, tp ) ))
|
||||||
|
shape_para( c, tp );
|
||||||
|
}
|
||||||
|
|
||||||
pFmt = tp->member.para.pFmt;
|
pFmt = tp->member.para.pFmt;
|
||||||
|
|
||||||
wc.context = c;
|
wc.context = c;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
WINE_DEFAULT_DEBUG_CHANNEL(richedit);
|
||||||
|
|
||||||
|
|
||||||
static BOOL
|
static BOOL
|
||||||
ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars);
|
ME_StreamOutRTFText(ME_OutStream *pStream, const WCHAR *text, LONG nChars);
|
||||||
|
|
||||||
|
|
|
@ -164,7 +164,7 @@ reactos/dll/win32/qmgrprxy # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/query # Synced to Wine-1.7.1
|
reactos/dll/win32/query # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/rasapi32 # Synced to Wine-1.7.1
|
reactos/dll/win32/rasapi32 # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/resutils # Synced to Wine-1.7.1
|
reactos/dll/win32/resutils # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/riched20 # Synced to Wine-1.7.1
|
reactos/dll/win32/riched20 # Synced to Wine-1.7.17
|
||||||
reactos/dll/win32/riched32 # Synced to Wine-1.7.1
|
reactos/dll/win32/riched32 # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/rpcrt4 # Synced to Wine-1.7.1
|
reactos/dll/win32/rpcrt4 # Synced to Wine-1.7.1
|
||||||
reactos/dll/win32/rsabase # Synced to Wine-1.7.1
|
reactos/dll/win32/rsabase # Synced to Wine-1.7.1
|
||||||
|
|
Loading…
Reference in a new issue