* Navigate to the requested file. * * @param newfile The file to navigate to. * @param line The line to scroll to. */
| 411 | * @param line The line to scroll to. |
| 412 | */ |
| 413 | void TextfileWindow::NavigateToFile(std::string newfile, size_t line) |
| 414 | { |
| 415 | /* Double-check that the file link begins with ./ as a relative path. */ |
| 416 | if (!newfile.starts_with("./")) return; |
| 417 | |
| 418 | /* Get the path portion of the current file path. */ |
| 419 | std::string newpath = this->filepath; |
| 420 | size_t pos = newpath.find_last_of(PATHSEPCHAR); |
| 421 | if (pos == std::string::npos) { |
| 422 | newpath.clear(); |
| 423 | } else { |
| 424 | newpath.erase(pos + 1); |
| 425 | } |
| 426 | |
| 427 | /* Check and remove for anchor in link. Do this before we find the filename, as people might have a / after the hash. */ |
| 428 | size_t anchor_pos = newfile.find_first_of('#'); |
| 429 | std::string anchor; |
| 430 | if (anchor_pos != std::string::npos) { |
| 431 | anchor = newfile.substr(anchor_pos); |
| 432 | newfile.erase(anchor_pos); |
| 433 | } |
| 434 | |
| 435 | /* Now the anchor is gone, check if this is a markdown or textfile. */ |
| 436 | if (!StrEndsWithIgnoreCase(newfile, ".md") && !StrEndsWithIgnoreCase(newfile, ".txt")) return; |
| 437 | |
| 438 | /* Convert link destination to acceptable local filename (replace forward slashes with correct path separator). */ |
| 439 | newfile = newfile.substr(2); |
| 440 | if (PATHSEPCHAR != '/') { |
| 441 | for (char &c : newfile) { |
| 442 | if (c == '/') c = PATHSEPCHAR; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | /* Paste the two together and check file exists. */ |
| 447 | newpath = newpath + newfile; |
| 448 | if (!FioCheckFileExists(newpath, NO_DIRECTORY)) return; |
| 449 | |
| 450 | /* Update history. */ |
| 451 | this->AppendHistory(newpath); |
| 452 | |
| 453 | /* Load the new file. */ |
| 454 | this->filepath = newpath; |
| 455 | this->filename = newpath.substr(newpath.find_last_of(PATHSEP) + 1); |
| 456 | |
| 457 | this->LoadTextfile(this->filepath, NO_DIRECTORY); |
| 458 | |
| 459 | this->GetScrollbar(WID_TF_HSCROLLBAR)->SetPosition(0); |
| 460 | this->GetScrollbar(WID_TF_VSCROLLBAR)->SetPosition(0); |
| 461 | |
| 462 | if (anchor.empty() || line != 0) { |
| 463 | this->ScrollToLine(line); |
| 464 | } else { |
| 465 | auto anchor_dest = std::ranges::find(this->link_anchors, anchor, &Hyperlink::destination); |
| 466 | if (anchor_dest != this->link_anchors.cend()) { |
| 467 | this->ScrollToLine(anchor_dest->line); |
| 468 | this->UpdateHistoryScrollpos(); |
| 469 | } else { |
| 470 | this->ScrollToLine(0); |
no test coverage detected