Notepad2添加定位光标到排版线快捷键

发现经常有这么一种需求: 从网上复制来文本粘贴到Notepad2里面通常都要格式化一下, 例如添加换行符, 排列的整齐一点儿. 我经常用的动作是将光标定位到排版线处然后Enter换行, 每次用鼠标太麻烦, 因此给他添加了一个快捷键.

实现这个功能涉及到三个主要函数: Document::FindColumn, Editor::MovePositionTo, 还有Editor::StartEndDisplayLine. 先看FindColumn

源码中的实现是

int Document::FindColumn(int lineint column) {
    int position LineStart(line);
    
    int columnCurrent 0;
    if ((line >= 0) && (line LinesTotal())) {
        while ((columnCurrent column) && (position Length())) {
            char ch cb.CharAt(position);
            if (ch == '\t') {
                columnCurrent NextTab(columnCurrenttabInChars);
                position++;
            else if (ch == '\r') {
                return position;
            else if (ch == '\n') {
                return position;
            else {
                //这样的话,一个汉字相当于一个column,一个tab键等同于4个中文
                //例如中英混排,一个中文相当于一个空格,可能要修正一下
                columnCurrent++;
                int oldpos position;
                //跳过一个字节或者是两个字节
                position MovePositionOutsideChar(position 11);
                //如果字符是一个中文,那么columnCurrent加2
                ifposition oldpos columnCurrent++;//多消耗一个column
                //已修正
            }
        }
    }
    return position;
    
}

这个函数从一行的开始处向右移动, 宽度由column指定, column可以是排版线的宽度. 这里默认是从一整行的开始处移动, 而我们需要的功能是要能够从窗口中的行的开始处移动, 也就是要考虑自动换行的情况. 所以应该将里面的循环独立出来. 修改之后如下

int Document::FindColumnFromPosint position int columns) {
    int columnCurrent 0;
    while ((columnCurrent columns) && (position Length())) {
        char ch cb.CharAt(position);
        if (ch == '\t') {
            columnCurrent NextTab(columnCurrenttabInChars);
            position++;
        else if (ch == '\r') {
            return position;
        else if (ch == '\n') {
            return position;
        else {
            //这样的话,一个汉字相当于一个column,一个tab键等同于4个中文
            //例如中英混排,一个中文相当于一个空格,可能要修正一下
            columnCurrent++;
            int oldpos position;
            //跳过一个字节或者是两个字节
            position MovePositionOutsideChar(position 11);
            //如果字符是一个中文,那么columnCurrent加2
            ifposition oldpos columnCurrent++;//多消耗一个column
            //已修正
        }
    }
    return position;
}

int Document::FindColumn(int lineint column) {
    int position LineStart(line);
    return FindColumnFromPospositioncolumn);
}

然后是StartEndDisplayLine, 这个函数可以从当前光标的位置得到所在行的行首的Position, 可以作为参数传递给FindColumnFromPos, 然后columns是排版线的宽度即可. 在Editor::KeyCommand中添加一个命令:

    case SCN_GOTOTYPESET:
        MovePositionTo(pdoc->FindColumnFromPos(StartEndDisplayLine(currentPos,true),
                        theEdge));
        SetLastXChosen();
        break;

最后再到资源管理器中添加一个快捷键, 我用的是CTRL + VK_OEM_7, 也就是单引号.

    case IDS_GOTOTYPESET:
        m_doc.SendMessageA(SCN_GOTOTYPESET,0,0);
        break;