Skip to content

Searching in the same row #48

@patient74

Description

@patient74

First of all thank you for the amazing tutorial! I came across an issue in search feature. When we press the arrow keys to find the next match, we move to the next or previous rows. But, there might be matches in the same row. Also, when we search in the reverse direction the match in the last position must be found. I tried implementing this by adding a new function editorFindRowLastMatch( ) and making changes to editorFindCallback( ) and it seems to work.

/*** find ***/
int editorFindRowLastMatch(erow* row, int start, int end, char* query) //find position of last match in a row
{
    int qlen = strlen(query);
    while (end >= start)
    {
        if (row->render[end] == query[0])
        {
            if (!strncmp(&row->render[end], query, qlen))
                return end;
        }
        end--;
    }
    return -1;
}

void editorFindCallback(char* query, int key) {
    static int last_match = -1;
    static int direction = 1;

    static int saved_hl_line;
    static char* saved_hl = NULL;

    if (saved_hl) {
        memcpy(E.row[saved_hl_line].hl, saved_hl, E.row[saved_hl_line].rsize);
        free(saved_hl);
        saved_hl = NULL;
    }

    if (key == '\r' || key == '\x1b') {
        last_match = -1;
        direction = 1;
        return;
    }
    else if (key == ARROW_RIGHT || key == ARROW_DOWN) {
        direction = 1;
    }
    else if (key == ARROW_LEFT || key == ARROW_UP) {
        direction = -1;
    }
    else {
        last_match = -1;
        direction = 1;
    }

    if (last_match == -1) direction = 1;
    int current = last_match;

    int rx = -1; //this variable will contain the postion of the match
    int same_row = 0; //if the match is found in the same row

    if (current != -1) //we check in the same row if there was a previous match
    {
       erow* row = &E.row[current];

        if (direction == 1)
        {
          char* match = strstr(&row->render[E.rx + 1], query); //find a match after the previous match position(E.rx) in the same row 
            if (match)
            {
                rx = match - row->render;
                E.cx = editorRowRxToCx(row, rx);
                same_row = 1;
            }
        }
        else //if in reverse direction
        {
            int lfound = editorFindRowLastMatch(row, 0, E.rx - 1, query); //find the first match before previous match in the same row
            if (lfound != -1)
            {
                rx = lfound;
                E.cx = editorRowRxToCx(row, rx);
                same_row = 1;
            }
        }

    }

    if (!same_row) // if match was not found in the same_row
    {
        int i;
        for (i = 0; i < E.numrows; i++)
        {
            current += direction;
            if (current == -1) current = E.numrows - 1;
            else if (current == E.numrows) current = 0;

            erow* row = &E.row[current];
            char* match = strstr(row->render, query);
            if (match)
            {
                last_match = current;
                E.cy = current;
                rx = match - row->render;
                
                if (direction == -1) //if match found and the direction is reverse we find the last match in that row 
                {
                    int lfound = editorFindRowLastMatch(row, rx + 1, row->rsize - strlen(query), query);
                    if (lfound != -1)
                    {
                        rx = lfound;
                    }
                }
                E.cx = editorRowRxToCx(row, rx);
                E.rowoff = E.numrows;
                break;
            }
        }
    }

    if (rx != -1) // highlight only when match is found
    {
        erow* row = &E.row[current];
        saved_hl_line = current;
        saved_hl = malloc(row->rsize);
        memcpy(saved_hl, row->hl, row->rsize);
        memset(&row->hl[rx], HL_MATCH, strlen(query));
    }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions