예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
파일: caret.c 프로젝트: AmesianX/wine
/* Finds the run and offset from the pixel position.
 *
 * x & y are pixel positions in virtual coordinates into the rich edit control,
 * so client coordinates must first be adjusted by the scroll position.
 *
 * returns TRUE if the result was exactly under the cursor, otherwise returns
 * FALSE, and result is set to the closest position to the coordinates.
 */
static BOOL ME_FindPixelPos(ME_TextEditor *editor, int x, int y,
                            ME_Cursor *result, BOOL *is_eol)
{
  ME_DisplayItem *p = editor->pBuffer->pFirst->member.para.next_para;
  BOOL isExact = TRUE;

  x -= editor->rcFormat.left;
  y -= editor->rcFormat.top;

  if (is_eol)
    *is_eol = FALSE;

  /* find paragraph */
  for (; p != editor->pBuffer->pLast; p = p->member.para.next_para)
  {
    assert(p->type == diParagraph);
    if (y < p->member.para.pt.y + p->member.para.nHeight)
    {
      if (p->member.para.nFlags & MEPF_ROWSTART)
        p = ME_FindPixelPosInTableRow(x, y, p);
      y -= p->member.para.pt.y;
      p = ME_FindItemFwd(p, diStartRow);
      break;
    } else if (p->member.para.nFlags & MEPF_ROWSTART) {
      p = ME_GetTableRowEnd(p);
    }
  }
  /* find row */
  for (; p != editor->pBuffer->pLast; )
  {
    ME_DisplayItem *pp;
    assert(p->type == diStartRow);
    if (y < p->member.row.pt.y + p->member.row.nHeight) break;
    pp = ME_FindItemFwd(p, diStartRow);
    if (!pp) break;
    p = pp;
  }
  if (p == editor->pBuffer->pLast)
  {
    /* The position is below the last paragraph, so the last row will be used
     * rather than the end of the text, so the x position will be used to
     * determine the offset closest to the pixel position. */
    isExact = FALSE;
    p = ME_FindItemBack(p, diStartRow);
    if (!p) p = editor->pBuffer->pLast;
  }

  assert( p->type == diStartRow || p == editor->pBuffer->pLast );

  if( p->type == diStartRow )
      return ME_FindRunInRow( editor, p, x, result, is_eol ) && isExact;

  result->pRun = ME_FindItemBack(p, diRun);
  result->pPara = ME_GetParagraph(result->pRun);
  result->nOffset = 0;
  assert(result->pRun->member.run.nFlags & MERF_ENDPARA);
  return FALSE;
}
예제 #4
0
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);
}
예제 #5
0
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);
}
예제 #6
0
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);
}