wine/dlls/riched20/row.c
Huw Davies ab95fb31fc riched20: Use row ptrs in the page up/down handlers.
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
2020-11-09 10:45:47 +01:00

155 lines
4.1 KiB
C

/*
* RichEdit - Operations on rows of text (rows are recreated during
* wrapping and are used for displaying the document, they don't keep any
* true document content; delete all rows, rewrap all paragraphs and
* you get them back).
*
* Copyright 2004 by Krzysztof Foltman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "editor.h"
ME_Row *row_next( ME_Row *row )
{
ME_DisplayItem *item;
item = ME_FindItemFwd( row_get_di( row ), diStartRowOrParagraphOrEnd );
if (!item || item->type != diStartRow) return NULL;
return &item->member.row;
}
ME_Row *row_next_all_paras( ME_Row *row )
{
ME_DisplayItem *item;
item = ME_FindItemFwd( row_get_di( row ), diStartRow );
if (!item) return NULL;
return &item->member.row;
}
ME_Row *row_prev_all_paras( ME_Row *row )
{
ME_DisplayItem *item;
item = ME_FindItemBack( row_get_di( row ), diStartRow );
if (!item) return NULL;
return &item->member.row;
}
ME_Run *row_first_run( ME_Row *row )
{
ME_DisplayItem *item;
item = ME_FindItemFwd( row_get_di( row ), diRunOrStartRow );
assert( item->type == diRun );
return &item->member.run;
}
ME_Run *row_next_run( ME_Row *row, ME_Run *run )
{
ME_DisplayItem *item;
assert( row == &ME_FindItemBack( run_get_di( run ), diStartRow )->member.row );
item = ME_FindItemFwd( run_get_di( run ), diRunOrStartRow );
if (!item || item->type == diStartRow) return NULL;
return &item->member.run;
}
ME_Row *row_from_cursor( ME_Cursor *cursor )
{
ME_DisplayItem *item;
item = ME_FindItemBack( run_get_di( cursor->run ), diStartRow );
return &item->member.row;
}
void row_first_cursor( ME_Row *row, ME_Cursor *cursor )
{
ME_DisplayItem *item;
item = ME_FindItemFwd( row_get_di( row ), diRun );
cursor->run = &item->member.run;
cursor->para = cursor->run->para;
cursor->nOffset = 0;
}
void row_end_cursor( ME_Row *row, ME_Cursor *cursor, BOOL include_eop )
{
ME_DisplayItem *item, *run;
item = ME_FindItemFwd( row_get_di( row ), diStartRowOrParagraphOrEnd );
run = ME_FindItemBack( item, diRun );
cursor->run = &run->member.run;
cursor->para = cursor->run->para;
cursor->nOffset = (item->type == diStartRow || include_eop) ? cursor->run->len : 0;
}
ME_Paragraph *row_para( ME_Row *row )
{
ME_Cursor cursor;
row_first_cursor( row, &cursor );
return cursor.para;
}
ME_Row *row_from_row_number( ME_TextEditor *editor, int row_num )
{
ME_Paragraph *para = editor_first_para( editor );
ME_Row *row;
int count = 0;
while (para_next( para ) && count + para->nRows <= row_num)
{
count += para->nRows;
para = para_next( para );
}
if (!para_next( para )) return NULL;
for (row = para_first_row( para ); row && count < row_num; count++)
row = row_next( row );
return row;
}
int row_number_from_char_ofs( ME_TextEditor *editor, int ofs )
{
ME_Paragraph *para = editor_first_para( editor );
ME_Row *row;
ME_Cursor cursor;
int row_num = 0;
while (para_next( para ) && para_next( para )->nCharOfs <= ofs)
{
row_num += para->nRows;
para = para_next( para );
}
if (para_next( para ))
{
for (row = para_first_row( para ); row; row = row_next( row ))
{
row_end_cursor( row, &cursor, TRUE );
if (ME_GetCursorOfs( &cursor ) > ofs ) break;
row_num++;
}
}
return row_num;
}