| Summary: | [PATCH] new feature: (global) cursor position history | ||
|---|---|---|---|
| Product: | [Applications] kdevelop | Reporter: | andreas braendle <abraendle> |
| Component: | bookmarks part | Assignee: | kdevelop-bugs-null |
| Status: | RESOLVED INTENTIONAL | ||
| Severity: | wishlist | ||
| Priority: | NOR | ||
| Version First Reported In: | unspecified | ||
| Target Milestone: | --- | ||
| Platform: | openSUSE | ||
| OS: | Linux | ||
| Latest Commit: | Version Fixed/Implemented In: | ||
| Sentry Crash Report: | |||
// CURSHIST.CPP
#include "curshist.h"
#include <string.h>
CGlobalCursorPosHistory::CGlobalCursorPosHistory()
{
m_hist = new CursHistEntry[GCPH_HISTSZ+2]; // +2 savety (+1 needed)
num=0; curr=0;
m_stack = new CursHistEntry[GCPH_HSTACK];
num_s=0;
}
CGlobalCursorPosHistory::~CGlobalCursorPosHistory()
{
delete[] m_hist;
}
void CGlobalCursorPosHistory::CursorChanged(QEditorWidget* FileId, int line, int column)
{
int newidx;
int currline=m_hist[curr].LineCol/256;
if (line>currline-GCPH_BLOCK && line<currline+GCPH_BLOCK) // replace Entry -- if we are withing same BLOCK
newidx = curr;
else {
// make room for new entry
newidx=curr+1;
memcpy((void*)&m_hist[newidx+1],(void*)&m_hist[newidx], (num-newidx-1)* sizeof(CursHistEntry));
// remark: might lead to GCPH_HISTSZ+1 entries, but this is ok!
num++;
// if too much entries, delete either the first or the last
if (GCPH_HISTSZ>num) {
if (newidx>(3*GCPH_HISTSZ)/5) // 60 % for history, 40 % for future
{
memcpy((void*)&m_hist[0],(void*)&m_hist[1], GCPH_HISTSZ*sizeof(CursHistEntry)); // delete first entry
newidx--;
} //else: do nothing // = delete last entry
num=GCPH_HISTSZ;
}
}
if (line>0xFFFFFF) line=0xFFFFFF;
if (line<0) line=0;
if (column>0xFF) column=0xFF;
if (column<0) column=0;
m_hist[newidx].FileId=FileId;
m_hist[newidx].LineCol=256*line+column;
}
void CGlobalCursorPosHistory::FileClosed(QEditorWidget* FileId)
{
for (int i=0; i<num; i++)
{
if (m_hist[i].FileId==FileId) {
memcpy((void*)&m_hist[i],(void*)&m_hist[i+1], (num-i-1)*sizeof(CursHistEntry));
num--;
if (curr>i) curr--;
if (curr>num-1) curr--;
}
}
}
/*
The following functions return:
the editor view to go to
line+column (returned by reference)
editor view=NULL always means don't change cursor position!
*/
QEditorWidget* CGlobalCursorPosHistory::NavigateBack(int &line, int &column)
{
if (num<=0) return NULL; // NULL: No History Entries exist yet, Navigation not possible
if (curr>=1) curr--;
line =m_hist[curr].LineCol / 256;
column=m_hist[curr].LineCol % 256;
return m_hist[curr].FileId;
}
QEditorWidget* CGlobalCursorPosHistory::NavigateForward(int &line, int &column)
{
if (num<=0) return NULL; // NULL: No History Entries exist yet
if (curr<num-1) curr++;
line =m_hist[curr].LineCol / 256;
column=m_hist[curr].LineCol % 256;
return m_hist[curr].FileId;
}
QEditorWidget* CGlobalCursorPosHistory::NavigateLeave(int &line, int &column) //PUSH
{
if (num<=0) return NULL; // NULL: No History Entries exist yet, Navigation not possible
// PUSH curr ON stack
// make space for one entry at 0
memcpy((void*)&m_stack[1],(void*)&m_stack[0], (GCPH_HSTACK-1)*sizeof(CursHistEntry));
m_stack[0].LineCol=m_hist[curr].LineCol;
m_stack[0].FileId =m_hist[curr].FileId;
num_s++; if (num_s>GCPH_HSTACK) num_s=GCPH_HSTACK;
num--;
return NavigateBack(line,column); // new position is curr-1
}
QEditorWidget* CGlobalCursorPosHistory::NavigatePop(int &line, int &column) //POP
{
if (num_s<=0) return NULL; // NULL: stack empty, Navigation not possible
// get topmost stack entry (=m_stack[0])
line =m_stack[0].LineCol / 256;
column =m_stack[0].LineCol % 256;
QEditorWidget* p=m_stack[0].FileId;
// insert the entry in history list
CursorChanged(p,line,column);
// delete topmost stack entry (=m_stack[0])
memcpy((void*)&m_stack[0],(void*)&m_stack[1], (GCPH_HSTACK-1)*sizeof(CursHistEntry));
num_s--;
return p;
}
// CURSHIST.H #ifndef CURSHIST_H #define CURSHIST_H // written by (C) Andreas Brändle <abraendle@gmx.de> 10.01.04 // published under GPL // TODO: Implement this useful feature also into other IDEs/editors!! /* You need: * 4 application-global keys: Left, Right, Up, Down (Light-version 2 keys: Right, Left -also possible) * one application-global object of this class * the editor-views must know about this object and inform it when the cursor position has changed, because - a character was entered - cursor keys pressed especially NOT when - Page/UpDown pressed - Mouse clicked also when a file/view is closed * catch the events for the 4 keys globally and change to the appropriate view+cursorposition thats all... */ // TODO: IMPORTANT! change the "QEditorWiget*"-pointers to what is needed to identify the view! class QEditorWidget; //DEL THIS LINE!! /**INTERNAL**/ struct CursHistEntry { QEditorWidget* FileId; int LineCol; // (Line 0..2^24-1) *256 + Column 0..255 to save memory }; const int GCPH_BLOCK=7; // num of lines within which a cursor movement is not to be stored twice const int GCPH_HISTSZ=260; // size of history list const int GCPH_HSTACK=16; // size of history stack /***BEGIN****/ /* Purpose: Implements a global cursor position history */ class CGlobalCursorPosHistory { public: CGlobalCursorPosHistory(); ~CGlobalCursorPosHistory(); // store/update positions void CursorChanged(QEditorWidget* FileId, int line, int column); // inform this class! void FileClosed(QEditorWidget* FileId); // clean up history list // get new position QEditorWidget* NavigateBack(int &line, int &column); // Ctrl-Alt-Left for example QEditorWidget* NavigateLeave(int &line, int &column); // Ctrl-Alt-Up for example QEditorWidget* NavigateForward(int &line, int &column); // Ctrl-Alt-Right for example QEditorWidget* NavigatePop(int &line, int &column); // Ctrl-Alt-Down for example private: CursHistEntry* m_hist; CursHistEntry* m_stack; int num; // number of valid entries int curr; // entry with last known cursor position (current) int num_s; // number of valid entries in stack }; /****END*****/ #endif CURSHIST_H the class itself is rather simple not much is needed apart from 4 keys & the ability to set a specific view+line+column "Also, History Back/Forward buttons will helps along with this "hypercode" walking." in Bug 62711 you don't understand this feature... or why is nobody interested??? it's such a nice feature for an editor, IMHO... No idea why this was put to the bookmarks plugin. Also, the patch seems to reference the QEditor, which has been removed. Closing. |
Version: (using KDE KDE 3.2.1) Installed from: SuSE RPMs OS: Linux i've written a class (some months ago) someone must intergrate it into kdevelop it's a pretty sophisticated feature already. description&howto is included ----------------- [...] // Documentation: // PURPOSE: // implements a global CursorPositionHistory for qeditor (?) etc. // usful when working with large projects/files, and having to do changes in several files // makes finding interesting positions again a lot easier (for example while browsing the code); // also useful during finding out how the code of a certain program is working // also useful when working only with a large single file, as i found out :) // can be more practical than & is not intended as a substitute for bookmarks Special features: - if navigating within a "block" of +/- 7 lines no additional history entry is inserted - if navigating back and then changing the cursor position, the "future" isn't deleted - NavigateLeave deletes the current entry out of the history list (=leave this position), (it also pushes it onto a small stack -> NavigatePop to get it back) ************************** I would have proposed to use the 4 keys Ctrl-Alt-Left/Right/Up/Down, but they seem to be already used for other purposes. ...Ctrl-Alt-Shift-Left/Right are also already used other proposals: Ctrl-Alt-Shift-j/k/l/i Ctrl-Alt-4/5/6/8 (Numpad) etc. ************************** ("light" version with 2 or 3 keys possible) QEditorWidget* NavigateBack(int &line, int &column); // Ctrl-Alt-Left for example QEditorWidget* NavigateLeave(int &line, int &column); // Ctrl-Alt-Up for example QEditorWidget* NavigateForward(int &line, int &column); // Ctrl-Alt-Right for example QEditorWidget* NavigatePop(int &line, int &column); // Ctrl-Alt-Down for example (3key-version: optional) stack: i Pos2 | Pos1 v | *---------------------* UP | DOWN | | history <<<<<-------- current ------------>>>> future LEFT RIGHT KEYPRESSED-EVENT: (PSEUDOCODE) int l,c; QEditorWidget* p; if (p=NavigateBack(l,c)) {setviewactive?(p); setcursor(p,l,c); } ************************** // INTEGRATION: [see source files] .... // perhaps the Application/mainwindow should catch these events and then change to the correct // editor-window+line+column // SideEffects/NECESSARY CHANGES to rest of the Editor-code: // uses QEditorWiget* pointers to identify which of the currently open files is meant // Editor Codes has to inform this Class and use it, and also inform it when a file is closed // Application has to create one object of this class