static void ME_ArrowPageDown(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pLast; int x, y; /* Find y position of the last row */ pLast = editor->pBuffer->pLast; y = pLast->member.para.prev_para->member.para.pt.y + ME_FindItemBack(pLast, diStartRow)->member.row.pt.y; x = ME_GetXForArrow(editor, pCursor); if (editor->vert_si.nPos >= y - editor->sizeWindow.cy) { pCursor->pRun = ME_FindItemBack(editor->pBuffer->pLast, diRun); pCursor->nOffset = 0; editor->bCaretAtEnd = FALSE; } else { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *p; int ys, yd, yp, yprev; int yOldScrollPos = editor->vert_si.nPos; 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; yprev = ys = y = yp + p->member.row.pt.y; /* For native richedit controls: * v1.0 - v3.1 can only scroll down as far as the scrollbar lets us * v4.1 can scroll past this position here. */ ME_ScrollDown(editor, editor->sizeWindow.cy); /* Only move the cursor by the amount scrolled. */ yd = y + editor->vert_si.nPos - yOldScrollPos; pLast = p; do { p = ME_FindItemFwd(p, diStartRowOrParagraph); if (!p) break; if (p->type == diParagraph) { yp = p->member.para.pt.y; continue; } y = yp + p->member.row.pt.y; if (y >= yd) break; pLast = p; yprev = y; } while(1); pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }
static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pItem; int x = ME_GetXForArrow(editor, pCursor); if (editor->bCaretAtEnd && !pCursor->nOffset) pRun = ME_FindItemBack(pRun, diRun); if (!pRun) return; if (nRelOfs == -1) { /* start of this row */ pItem = ME_FindItemBack(pRun, diStartRow); assert(pItem); /* start of the previous row */ pItem = ME_FindItemBack(pItem, diStartRow); } else { /* start of the next row */ pItem = ME_FindItemFwd(pRun, diStartRow); /* FIXME If diParagraph is before diStartRow, wrap the next paragraph? */ } if (!pItem) { /* row not found - ignore */ return; } pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd); assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }
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) { pCursor->pRun = ME_FindItemFwd(editor->pBuffer->pFirst, diRun); pCursor->nOffset = 0; 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, ys, yd, yp, yprev; 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; yprev = ys = 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; yprev = y; } while(1); pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }
static void ME_ArrowPageUp(ME_TextEditor *editor, ME_Cursor *pCursor) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pLast, *p; int x, y, ys, yd, yp, yprev; ME_Cursor tmp_curs = *pCursor; 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.nYPos; yprev = ys = y = yp + p->member.row.nYPos; yd = y - editor->sizeWindow.cy; 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.nYPos; continue; } y = yp + p->member.row.nYPos; if (y < yd) break; pLast = p; yprev = y; } while(1); pCursor->pRun = ME_FindRunInRow(editor, pLast, x, &pCursor->nOffset, &editor->bCaretAtEnd); ME_UpdateSelection(editor, &tmp_curs); if (yprev < editor->sizeWindow.cy) { ME_EnsureVisible(editor, ME_FindItemFwd(editor->pBuffer->pFirst, diRun)); ME_Repaint(editor); } else { ME_ScrollUp(editor, ys-yprev); } assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }
static void ME_MoveCursorLines(ME_TextEditor *editor, ME_Cursor *pCursor, int nRelOfs) { ME_DisplayItem *pRun = pCursor->pRun; ME_DisplayItem *pItem, *pOldPara, *pNewPara; int x = ME_GetXForArrow(editor, pCursor); if (editor->bCaretAtEnd && !pCursor->nOffset) pRun = ME_FindItemBack(pRun, diRun); if (!pRun) return; pOldPara = ME_GetParagraph(pRun); if (nRelOfs == -1) { /* start of this row */ pItem = ME_FindItemBack(pRun, diStartRow); assert(pItem); /* start of the previous row */ pItem = ME_FindItemBack(pItem, diStartRow); if (!pItem) return; /* row not found - ignore */ pNewPara = ME_GetParagraph(pItem); if (pOldPara->member.para.nFlags & MEPF_ROWEND || (pOldPara->member.para.pCell && pOldPara->member.para.pCell != pNewPara->member.para.pCell)) { /* Brought out of a cell */ pNewPara = ME_GetTableRowStart(pOldPara)->member.para.prev_para; if (pNewPara->type == diTextStart) return; /* At the top, so don't go anywhere. */ pItem = ME_FindItemFwd(pNewPara, diStartRow); } if (pNewPara->member.para.nFlags & MEPF_ROWEND) { /* Brought into a table row */ ME_Cell *cell = &ME_FindItemBack(pNewPara, diCell)->member.cell; while (x < cell->pt.x && cell->prev_cell) cell = &cell->prev_cell->member.cell; if (cell->next_cell) /* else - we are still at the end of the row */ pItem = ME_FindItemBack(cell->next_cell, diStartRow); } } else { /* start of the next row */ pItem = ME_FindItemFwd(pRun, diStartRow); if (!pItem) return; /* row not found - ignore */ /* FIXME If diParagraph is before diStartRow, wrap the next paragraph? */ pNewPara = ME_GetParagraph(pItem); if (pOldPara->member.para.nFlags & MEPF_ROWSTART || (pOldPara->member.para.pCell && pOldPara->member.para.pCell != pNewPara->member.para.pCell)) { /* Brought out of a cell */ pNewPara = ME_GetTableRowEnd(pOldPara)->member.para.next_para; if (pNewPara->type == diTextEnd) return; /* At the bottom, so don't go anywhere. */ pItem = ME_FindItemFwd(pNewPara, diStartRow); } if (pNewPara->member.para.nFlags & MEPF_ROWSTART) { /* Brought into a table row */ ME_DisplayItem *cell = ME_FindItemFwd(pNewPara, diCell); while (cell->member.cell.next_cell && x >= cell->member.cell.next_cell->member.cell.pt.x) cell = cell->member.cell.next_cell; pItem = ME_FindItemFwd(cell, diStartRow); } } if (!pItem) { /* row not found - ignore */ return; } pCursor->pRun = ME_FindRunInRow(editor, pItem, x, &pCursor->nOffset, &editor->bCaretAtEnd); assert(pCursor->pRun); assert(pCursor->pRun->type == diRun); }