static void ME_SelectByType(ME_TextEditor *editor, ME_SelectionType selectionType) { /* pCursor[0] is the end of the selection * pCursor[1] is the start of the selection (or the position selection anchor) * pCursor[2] and [3] are the selection anchors that are backed up * so they are kept when the selection changes for drag selection. */ editor->nSelectionType = selectionType; switch(selectionType) { case stPosition: break; case stWord: ME_MoveCursorWords(editor, &editor->pCursors[0], +1); editor->pCursors[1] = editor->pCursors[0]; ME_MoveCursorWords(editor, &editor->pCursors[1], -1); break; case stLine: case stParagraph: { ME_DisplayItem *pItem; ME_DIType fwdSearchType, backSearchType; if (selectionType == stParagraph) { backSearchType = diParagraph; fwdSearchType = diParagraphOrEnd; } else { backSearchType = diStartRow; fwdSearchType = diStartRowOrParagraphOrEnd; } pItem = ME_FindItemFwd(editor->pCursors[0].pRun, fwdSearchType); assert(pItem); if (pItem->type == diTextEnd) editor->pCursors[0].pRun = ME_FindItemBack(pItem, diRun); else editor->pCursors[0].pRun = ME_FindItemFwd(pItem, diRun); editor->pCursors[0].pPara = ME_GetParagraph(editor->pCursors[0].pRun); editor->pCursors[0].nOffset = 0; pItem = ME_FindItemBack(pItem, backSearchType); editor->pCursors[1].pRun = ME_FindItemFwd(pItem, diRun); editor->pCursors[1].pPara = ME_GetParagraph(editor->pCursors[1].pRun); editor->pCursors[1].nOffset = 0; break; } case stDocument: /* Select everything with cursor anchored from the start of the text */ editor->nSelectionType = stDocument; ME_SetCursorToStart(editor, &editor->pCursors[1]); ME_SetCursorToEnd(editor, &editor->pCursors[0]); break; default: assert(0); } /* Store the anchor positions for extending the selection. */ editor->pCursors[2] = editor->pCursors[0]; editor->pCursors[3] = editor->pCursors[1]; }
static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *p = ME_FindItemFwd(editor->pBuffer->pFirst, diStartRow); if (editor->vert_si.nPos < p->member.row.nHeight) { ME_SetCursorToStart(editor, pCursor); editor->bCaretAtEnd = FALSE; /* Native clears seems to clear this x value on page up at the top * of the text, but not on page down at the end of the text. * Doesn't make sense, but we try to be bug for bug compatible. */ editor->nUDArrowX = -1; } else { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pLast; int x, y, yd, yp; int yOldScrollPos = editor->vert_si.nPos; x = ME_GetXForArrow(editor, pCursor); if (!pCursor->nOffset && editor->bCaretAtEnd) pRun = ME_FindItemBack(pRun, diRun); p = ME_FindItemBack(pRun, diStartRowOrParagraph); assert(p->type == diStartRow); yp = ME_FindItemBack(p, diParagraph)->member.para.pt.y; y = yp + p->member.row.pt.y; ME_ScrollUp(editor, editor->sizeWindow.cy); /* Only move the cursor by the amount scrolled. */ yd = y + editor->vert_si.nPos - yOldScrollPos; pLast = p; do { p = ME_FindItemBack(p, diStartRowOrParagraph); if (!p) break; if (p->type == diParagraph) { /* crossing paragraphs */ if (p->member.para.prev_para == NULL) break; yp = p->member.para.prev_para->member.para.pt.y; continue; } y = yp + p->member.row.pt.y; if (y < yd) break; pLast = p; } while(1); pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); pCursor->pPara = ME_GetParagraph(pCursor->pRun); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }
DECLSPEC_HIDDEN HRESULT WINAPI fnTextSrv_TxSetText(ITextServices *iface, LPCWSTR pszText) { ITextServicesImpl *This = impl_from_ITextServices(iface); ME_Cursor cursor; ME_SetCursorToStart(This->editor, &cursor); ME_InternalDeleteText(This->editor, &cursor, ME_GetTextLength(This->editor), FALSE); ME_InsertTextFromCursor(This->editor, 0, pszText, -1, This->editor->pBuffer->pDefaultStyle); ME_SetSelection(This->editor, 0, 0); This->editor->nModifyStep = 0; OleFlushClipboard(); ME_EmptyUndoStack(This->editor); ME_UpdateRepaint(This->editor, FALSE); return S_OK; }
/* Move the cursor nRelOfs characters (either forwards or backwards) * * returns the actual number of characters moved. **/ int ME_MoveCursorChars(ME_TextEditor *editor, ME_Cursor *cursor, int nRelOfs) { cursor->nOffset += nRelOfs; if (cursor->nOffset < 0) { cursor->nOffset += cursor->pRun->member.run.nCharOfs; if (cursor->nOffset >= 0) { /* new offset in the same paragraph */ do { cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); } while (cursor->nOffset < cursor->pRun->member.run.nCharOfs); cursor->nOffset -= cursor->pRun->member.run.nCharOfs; return nRelOfs; } cursor->nOffset += cursor->pPara->member.para.nCharOfs; if (cursor->nOffset <= 0) { /* moved to the start of the text */ nRelOfs -= cursor->nOffset; ME_SetCursorToStart(editor, cursor); return nRelOfs; } /* new offset in a previous paragraph */ do { cursor->pPara = cursor->pPara->member.para.prev_para; } while (cursor->nOffset < cursor->pPara->member.para.nCharOfs); cursor->nOffset -= cursor->pPara->member.para.nCharOfs; cursor->pRun = ME_FindItemBack(cursor->pPara->member.para.next_para, diRun); while (cursor->nOffset < cursor->pRun->member.run.nCharOfs) { cursor->pRun = ME_FindItemBack(cursor->pRun, diRun); } cursor->nOffset -= cursor->pRun->member.run.nCharOfs; } else if (cursor->nOffset >= cursor->pRun->member.run.len) { ME_DisplayItem *next_para; int new_offset; new_offset = ME_GetCursorOfs(cursor); next_para = cursor->pPara->member.para.next_para; if (new_offset < next_para->member.para.nCharOfs) { /* new offset in the same paragraph */ do { cursor->nOffset -= cursor->pRun->member.run.len; cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); } while (cursor->nOffset >= cursor->pRun->member.run.len); return nRelOfs; } if (new_offset >= ME_GetTextLength(editor)) { /* new offset at the end of the text */ ME_SetCursorToEnd(editor, cursor); nRelOfs -= new_offset - ME_GetTextLength(editor); return nRelOfs; } /* new offset in a following paragraph */ do { cursor->pPara = next_para; next_para = next_para->member.para.next_para; } while (new_offset >= next_para->member.para.nCharOfs); cursor->nOffset = new_offset - cursor->pPara->member.para.nCharOfs; cursor->pRun = ME_FindItemFwd(cursor->pPara, diRun); while (cursor->nOffset >= cursor->pRun->member.run.len) { cursor->nOffset -= cursor->pRun->member.run.len; cursor->pRun = ME_FindItemFwd(cursor->pRun, diRun); } } /* else new offset is in the same run */ return nRelOfs; }
static void ME_ArrowCtrlHome(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_SetCursorToStart(editor, pCursor); editor->bCaretAtEnd = FALSE; }
int ME_SetSelection(ME_TextEditor *editor, int from, int to) { int selectionEnd = 0; const int len = ME_GetTextLength(editor); /* all negative values are effectively the same */ if (from < 0) from = -1; if (to < 0) to = -1; /* select all */ if (from == 0 && to == -1) { ME_SetCursorToStart(editor, &editor->pCursors[1]); ME_SetCursorToEnd(editor, &editor->pCursors[0]); editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len; ME_InvalidateSelection(editor); return len + 1; } /* if both values are equal and also out of bound, that means to */ /* put the selection at the end of the text */ if ((from == to) && (to < 0 || to > len)) { selectionEnd = 1; } else { /* if from is negative and to is positive then selection is */ /* deselected and caret moved to end of the current selection */ if (from < 0) { int start, end; ME_GetSelectionOfs(editor, &start, &end); if (start != end) { if (end > len) { editor->pCursors[0].nOffset = 0; end --; } editor->pCursors[1] = editor->pCursors[0]; ME_Repaint(editor); } return end; } /* adjust to if it's a negative value */ if (to < 0) to = len + 1; /* flip from and to if they are reversed */ if (from>to) { int tmp = from; from = to; to = tmp; } /* after fiddling with the values, we find from > len && to > len */ if (from > len) selectionEnd = 1; /* special case with to too big */ else if (to > len) to = len + 1; } if (selectionEnd) { ME_SetCursorToEnd(editor, &editor->pCursors[0]); editor->pCursors[1] = editor->pCursors[0]; ME_InvalidateSelection(editor); return len; } ME_CursorFromCharOfs(editor, from, &editor->pCursors[1]); editor->pCursors[0] = editor->pCursors[1]; ME_MoveCursorChars(editor, &editor->pCursors[0], to - from); /* Selection is not allowed in the middle of an end paragraph run. */ if (editor->pCursors[1].pRun->member.run.nFlags & MERF_ENDPARA) editor->pCursors[1].nOffset = 0; if (editor->pCursors[0].pRun->member.run.nFlags & MERF_ENDPARA) { if (to > len) editor->pCursors[0].nOffset = editor->pCursors[0].pRun->member.run.len; else editor->pCursors[0].nOffset = 0; } return to; }