lc-soft / LCUI

C library for building user interfaces
https://lcui-dev.github.io
MIT License
4.12k stars 356 forks source link

TextEdit 删除文字BUG #270

Open zhaozheng0612 opened 2 years ago

zhaozheng0612 commented 2 years ago

存在问题的函数:

https://github.com/lc-soft/LCUI/blob/ea409f1339580c2f5267597a134c0a8c17d1e5e5/src/font/textlayer.c#L962-L967

  1. TextEdit启用多行文本
  2. 添加多行文本(‘\n’),如:123\n123\n123\n
  3. 用退格键(backspace)删除最后一行文本的最后一个字是出现异常,
        /* 如果当前行为空,也不是第一行,并且上一行没有结束符 */
        if (len <= 0 && end_y > 0 &&
            prev_txtrow->eol != LCUI_EOL_NONE) {
            TextRowList_RemoveRow(&layer->text_rows, end_y);
            return 0;    <<这里添加return可以解决bug
        }
        /* 调整起始行的容量 */
        TextRow_SetLength(txtrow, len);    <<< 这里异常,因为txtrow已经被释放掉了(TextRowList_RemoveRow)
  1. 在第二行最后一个字符处使用删除键(delete),出现异常:
    i = char_x;
    j = end_x;  <<< 原始代码这里为end_x + 1,这里不应该+1
    end_y = char_y + 1;
    /* 将结束行的内容拼接至起始行 */
    for (; i < len && j < end_txtrow->length; ++i, ++j) {
        txtrow->string[i] = end_txtrow->string[j];      <<< **这里吧下一行的字符数据与当前行进行拼接**
    }
    TextLayer_UpdateRowSize(layer, txtrow);
    TextLayer_InvalidateRowRect(layer, end_y, 0, -1);
    /* 移除结束行 */
    TextRowList_RemoveRow(&layer->text_rows, end_y);   <<< **这里释放掉原来行的LCUI_TextRow,形成空指针。**
    /* 如果起始行无内容,并且上一行没有结束符(换行符),则
     * 说明需要删除起始行 */
    if (len <= 0 && char_y > 0 && prev_txtrow->eol != LCUI_EOL_NONE) {
        TextLayer_InvalidateRowRect(layer, char_y, 0, -1);
        TextRowList_RemoveRow(&layer->text_rows, char_y);
    }
    TextLayer_AddUpdateTypeset(layer, char_y);