239 lines
6.9 KiB
C++
239 lines
6.9 KiB
C++
#ifndef _WDL_CURSESEDITOR_H_
|
|
#define _WDL_CURSESEDITOR_H_
|
|
|
|
#include "../wdlstring.h"
|
|
#include "../ptrlist.h"
|
|
#include "../destroycheck.h"
|
|
#include "curses.h"
|
|
#include <time.h>
|
|
|
|
class WDL_CursesEditor
|
|
{
|
|
public:
|
|
WDL_CursesEditor(void *cursesCtx);
|
|
virtual ~WDL_CursesEditor();
|
|
|
|
bool IsDirty() const { return m_clean_undopos != m_undoStack_pos; }
|
|
void SetDirty() { m_clean_undopos = -1; }
|
|
|
|
virtual int onChar(int c);
|
|
virtual void onRightClick(HWND hwnd) { }
|
|
|
|
virtual int updateFile(); // saves file on disk
|
|
void RunEditor(); // called from timer/main loop when on simulated curses -- if on a real console just call onChar(getch())
|
|
|
|
void *m_cursesCtx; // win32CursesCtx *
|
|
|
|
int m_top_margin, m_bottom_margin;
|
|
|
|
const char *GetFileName() { return m_filename.Get(); }
|
|
time_t GetLastModTime() const { return m_filelastmod; } // returns file mod time of last save or load, or 0 if unknown
|
|
void SetLastModTime(time_t v) { m_filelastmod=v; } // in case caller wants to manually set this value
|
|
|
|
virtual void setCursor(int isVscroll=0, double ycenter=-1.0);
|
|
void setCursorIfVisible();
|
|
|
|
int m_indent_size;
|
|
int m_max_undo_states;
|
|
|
|
virtual int init(const char *fn, const char *init_if_empty=0);
|
|
virtual int reload_file(bool clearUndo=false);
|
|
virtual void draw(int lineidx=-1);
|
|
|
|
virtual void highlight_line(int line);
|
|
|
|
void GoToLine(int line, bool dosel);
|
|
|
|
enum
|
|
{
|
|
#ifdef WDL_IS_FAKE_CURSES
|
|
SYNTAX_REGVAR = COLOR_PAIR(8),
|
|
SYNTAX_KEYWORD = COLOR_PAIR(9),
|
|
SYNTAX_STRING = COLOR_PAIR(10),
|
|
SYNTAX_STRINGVAR = COLOR_PAIR(11),
|
|
COLOR_MESSAGE = COLOR_PAIR(12),
|
|
COLOR_TOPLINE = COLOR_PAIR(13),
|
|
SYNTAX_FUNC2 = COLOR_PAIR(14),
|
|
#else
|
|
SYNTAX_REGVAR = COLOR_PAIR(4),
|
|
SYNTAX_KEYWORD = COLOR_PAIR(4),
|
|
SYNTAX_STRING = COLOR_PAIR(3),
|
|
SYNTAX_STRINGVAR = COLOR_PAIR(4),
|
|
COLOR_TOPLINE = COLOR_PAIR(6),
|
|
|
|
COLOR_MESSAGE = COLOR_PAIR(2),
|
|
SYNTAX_FUNC2 = COLOR_PAIR(7),
|
|
#endif
|
|
COLOR_BOTTOMLINE = COLOR_PAIR(1),
|
|
COLOR_SELECTION = COLOR_PAIR(2),
|
|
SYNTAX_HIGHLIGHT1 = COLOR_PAIR(3),
|
|
SYNTAX_HIGHLIGHT2 = COLOR_PAIR(4),
|
|
SYNTAX_COMMENT = COLOR_PAIR(5),
|
|
SYNTAX_ERROR = COLOR_PAIR(6),
|
|
SYNTAX_FUNC = COLOR_PAIR(7),
|
|
};
|
|
|
|
|
|
protected:
|
|
class refcntString;
|
|
class editUndoRec;
|
|
|
|
void loadLines(FILE* fh);
|
|
void getLinesFromClipboard(WDL_FastString &buf, WDL_PtrList<const char> &lines);
|
|
|
|
void draw_message(const char *str);
|
|
void draw_status_state();
|
|
|
|
virtual const char *sh_tokenize(const char **ptr, const char *endptr, int *lenOut, int *state) {
|
|
while (**ptr == ' ' || **ptr == '\t') (*ptr)++;
|
|
const char *ret = *ptr;
|
|
while (**ptr && (**ptr != ' ' && **ptr != '\t')) (*ptr)++;
|
|
*lenOut = (int) (*ptr - ret);
|
|
if (state) *state = 0;
|
|
return *ptr > ret ? ret : NULL;
|
|
}
|
|
|
|
#ifdef WDL_IS_FAKE_CURSES
|
|
virtual LRESULT onMouseMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
|
static LRESULT _onMouseMessage(void *user_data, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
if (user_data) return ((WDL_CursesEditor*)user_data)->onMouseMessage(hwnd,uMsg,wParam,lParam);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
virtual int search_line(const char *str, const WDL_FastString *line, int startpos, bool backwards, int *match_len); // returns offset of next match, or -1 if none
|
|
void runSearch(bool backwards, bool replaceAll);
|
|
|
|
void indentSelect(int amt);
|
|
void removeSelect();
|
|
void getselectregion(int &minx, int &miny, int &maxx, int &maxy);
|
|
void doDrawString(int y, int line_n, const char *p, int *c_comment_state);
|
|
|
|
void saveUndoState(); // updates rec[0]/rec[1], rec[0] is view after edit (rec[1] will be view after following edit)
|
|
void preSaveUndoState(); // updates coordinates of edit to last rec[1]
|
|
void loadUndoState(editUndoRec *rec, int idx); // idx=0 on redo, 1=on undo
|
|
|
|
void updateLastModTime();
|
|
|
|
virtual int GetCommentStateForLineStart(int line); // pass current line, returns flags (which will be passed as c_comment_state)
|
|
|
|
virtual void draw_line_highlight(int y, const char *p, int *c_comment_state, int line_n);
|
|
virtual void draw_top_line();
|
|
virtual void draw_bottom_line();
|
|
virtual bool LineCanAffectOtherLines(const char *txt, int spos, int slen) // if multiline comment etc
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual int GetTabCount() { return 1; }
|
|
virtual WDL_CursesEditor *GetTab(int idx) { if (idx==0) return this; return NULL; }
|
|
virtual bool AddTab(const char *fn) { return false; }
|
|
virtual void SwitchTab(int idx, bool rel) { }
|
|
virtual void CloseCurrentTab() { }
|
|
|
|
void OpenFileInTab(const char *fnp); // requires full pathname, will prompt to create if does not exist
|
|
|
|
int getVisibleLines() const;
|
|
|
|
WDL_FastString m_filename;
|
|
WDL_FastString m_newfn;
|
|
|
|
time_t m_filelastmod; // last written-to or read-from modification time, or 0 if unknown
|
|
int m_newline_mode; // detected from input. 0 = \n, 1=\r\n
|
|
|
|
// auto-detected on input, set to >0 (usually m_indent_size) if all leading whitespace was tabs (some fuzzy logic too)
|
|
// this is a workaround until we retrofit real tab (and UTF-8) support
|
|
int m_write_leading_tabs;
|
|
|
|
WDL_PtrList<WDL_FastString> m_text;
|
|
WDL_PtrList<editUndoRec> m_undoStack;
|
|
int m_undoStack_pos;
|
|
int m_clean_undopos;
|
|
|
|
enum uiState {
|
|
UI_STATE_NORMAL=0,
|
|
UI_STATE_MESSAGE,
|
|
UI_STATE_SEARCH,
|
|
UI_STATE_REPLACE,
|
|
UI_STATE_GOTO_LINE,
|
|
UI_STATE_SAVE_AS_NEW,
|
|
UI_STATE_SAVE_ON_CLOSE
|
|
};
|
|
uiState m_ui_state;
|
|
|
|
int m_selecting;
|
|
int m_select_x1,m_select_y1,m_select_x2,m_select_y2;
|
|
|
|
int m_offs_x;
|
|
int m_curs_x, m_curs_y;
|
|
int m_want_x; // to restore active column when vscrolling
|
|
|
|
int m_scrollcap; // 1=top, 2=bottom, 3=divider
|
|
int m_scrollcap_yoffs;
|
|
|
|
int m_curpane;
|
|
double m_pane_div;
|
|
int m_paneoffs_y[2];
|
|
int m_status_lastlen; // status line right hand text length, if any
|
|
|
|
int GetPaneDims(int* paney, int* paneh);
|
|
|
|
int m_line_editor_edited;
|
|
void run_line_editor(int c, WDL_FastString *fs);
|
|
WDL_FastString m_search_string, m_replace_string;
|
|
|
|
public:
|
|
static int s_overwrite;
|
|
static int s_search_mode;
|
|
protected:
|
|
static WDL_FastString s_fake_clipboard;
|
|
|
|
class refcntString
|
|
{
|
|
~refcntString() { free(str); }
|
|
char *str;
|
|
int str_len;
|
|
int refcnt;
|
|
public:
|
|
refcntString(const char *val, int val_len)
|
|
{
|
|
str_len = val_len;
|
|
str=(char*)malloc(str_len+1);
|
|
if (str) memcpy(str,val,str_len+1);
|
|
refcnt=0;
|
|
}
|
|
|
|
void AddRef() { refcnt++; }
|
|
void Release() { if (!--refcnt) delete this; }
|
|
|
|
const char *getStr() const { return str?str:""; }
|
|
int getStrLen() const { return str_len; }
|
|
};
|
|
class editUndoRec
|
|
{
|
|
public:
|
|
editUndoRec() { }
|
|
~editUndoRec()
|
|
{
|
|
int x;
|
|
for (x=0;x<m_htext.GetSize();x++)
|
|
{
|
|
refcntString *rs=m_htext.Get(x);
|
|
if (rs) rs->Release();
|
|
}
|
|
m_htext.Empty();
|
|
}
|
|
|
|
WDL_PtrList<refcntString> m_htext;
|
|
|
|
int m_offs_x[2];
|
|
int m_curs_x[2], m_curs_y[2];
|
|
int m_curpaneoffs_y[2];
|
|
};
|
|
void do_paste_lines(WDL_PtrList<const char> &lines);
|
|
public:
|
|
WDL_DestroyState destroy_check;
|
|
};
|
|
#endif
|