add oversampler
This commit is contained in:
215
oversampling/WDL/win32_curses/curses.h
Normal file
215
oversampling/WDL/win32_curses/curses.h
Normal file
@@ -0,0 +1,215 @@
|
||||
#ifndef _CURSES_WIN32SIM_H_
|
||||
#define _CURSES_WIN32SIM_H_
|
||||
|
||||
#if !defined(_WIN32) && !defined(MAC_NATIVE) && !defined(FORCE_WIN32_CURSES)
|
||||
#ifdef MAC
|
||||
#include <ncurses.h>
|
||||
#else
|
||||
#include <curses.h>
|
||||
#endif
|
||||
#else
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
|
||||
#include "../wdltypes.h"
|
||||
|
||||
|
||||
/*
|
||||
** this implements a tiny subset of curses on win32.
|
||||
** It creates a window (Resizeable by user), and gives you a callback to run
|
||||
** your UI.
|
||||
*/
|
||||
|
||||
|
||||
// if you need multiple contexts, define this in your sourcefiles BEFORE including curses.h
|
||||
// if you don't need multiple contexts, declare win32CursesCtx g_curses_context; in one of your source files.
|
||||
#ifndef CURSES_INSTANCE
|
||||
#define CURSES_INSTANCE (&g_curses_context)
|
||||
#endif
|
||||
|
||||
#define LINES ((CURSES_INSTANCE)->lines)
|
||||
#define COLS ((CURSES_INSTANCE)->cols)
|
||||
|
||||
//ncurses WIN32 wrapper functions
|
||||
|
||||
#define WDL_IS_FAKE_CURSES
|
||||
|
||||
#define addnstr(str,n) __addnstr(CURSES_INSTANCE,str,n)
|
||||
#define addstr(str) __addnstr(CURSES_INSTANCE,str,-1)
|
||||
#define addnstr_w(str,n) __addnstr_w(CURSES_INSTANCE,str,n)
|
||||
#define addstr_w(str) __addnstr_w(CURSES_INSTANCE,str,-1)
|
||||
#define addch(c) __addch(CURSES_INSTANCE,c)
|
||||
|
||||
#define mvaddstr(y,x,str) __mvaddnstr(CURSES_INSTANCE,y,x,str,-1)
|
||||
#define mvaddnstr(y,x,str,n) __mvaddnstr(CURSES_INSTANCE,y,x,str,n)
|
||||
#define mvaddstr_w(y,x,str) __mvaddnstr_w(CURSES_INSTANCE,y,x,str,-1)
|
||||
#define mvaddnstr_w(y,x,str,n) __mvaddnstr_w(CURSES_INSTANCE,y,x,str,n)
|
||||
#define clrtoeol() __clrtoeol(CURSES_INSTANCE)
|
||||
#define move(y,x) __move(CURSES_INSTANCE,y,x,0)
|
||||
#define attrset(a) (CURSES_INSTANCE)->m_cur_attr=(a)
|
||||
#define bkgdset(a) (CURSES_INSTANCE)->m_cur_erase_attr=(a)
|
||||
#define initscr() __initscr(CURSES_INSTANCE)
|
||||
#define endwin() __endwin(CURSES_INSTANCE)
|
||||
#define curses_erase(x) __curses_erase(x)
|
||||
#define start_color()
|
||||
#define init_pair(x,y,z) __init_pair((CURSES_INSTANCE),x,y,z)
|
||||
#define has_colors() 1
|
||||
|
||||
#define A_NORMAL 0
|
||||
#define A_BOLD 1
|
||||
#define COLOR_PAIR(x) ((x)<<NUM_ATTRBITS)
|
||||
#define COLOR_PAIRS 16
|
||||
#define NUM_ATTRBITS 1
|
||||
|
||||
#define WIN32_CURSES_CURSOR_TYPE_VERTBAR 0
|
||||
#define WIN32_CURSES_CURSOR_TYPE_HORZBAR 1
|
||||
#define WIN32_CURSES_CURSOR_TYPE_BLOCK 2
|
||||
|
||||
typedef struct win32CursesFB {
|
||||
wchar_t c;
|
||||
unsigned char attr;
|
||||
} win32CursesFB;
|
||||
|
||||
typedef struct win32CursesCtx
|
||||
{
|
||||
HWND m_hwnd;
|
||||
int lines, cols;
|
||||
|
||||
int want_scrollbar;
|
||||
int scrollbar_topmargin,scrollbar_botmargin;
|
||||
int drew_scrollbar[2];
|
||||
int offs_y[2];
|
||||
int div_y, tot_y;
|
||||
int scroll_y[2], scroll_h[2];
|
||||
|
||||
int m_cursor_x, m_cursor_y;
|
||||
int cursor_state_lx,cursor_state_ly; // used to detect changes and reset cursor_state
|
||||
|
||||
win32CursesFB *m_framebuffer;
|
||||
HFONT mOurFont;
|
||||
int *fontsize_ptr;
|
||||
|
||||
int m_font_w, m_font_h;
|
||||
|
||||
int colortab[COLOR_PAIRS << NUM_ATTRBITS][2];
|
||||
|
||||
int m_kb_queue[64];
|
||||
unsigned char m_kb_queue_valid;
|
||||
unsigned char m_kb_queue_pos;
|
||||
|
||||
char need_redraw; // &2 = need font calculation, &1 = need redraw, &4=full paint pending, no need to keep invalidating
|
||||
char cursor_state; // blinky cycle
|
||||
|
||||
char m_cur_attr;
|
||||
char m_cur_erase_attr;
|
||||
|
||||
// callbacks/config available for user
|
||||
char want_getch_runmsgpump; // set to 1 to cause getch() to run the message pump, 2 to cause it to be blocking (waiting for keychar)
|
||||
char cursor_type; // set to WIN32_CURSES_CURSOR_TYPE_VERTBAR etc
|
||||
|
||||
void (*do_update)(win32CursesCtx *ctx); // called on resize/etc, to avoid flicker. NULL will use default behavior
|
||||
|
||||
void *user_data;
|
||||
LRESULT (*onMouseMessage)(void *user_data, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
int *user_colortab; // cycle the high byte of the first entry to force an update of colortab
|
||||
int user_colortab_lastfirstval;
|
||||
} win32CursesCtx;
|
||||
|
||||
extern win32CursesCtx g_curses_context; // declare this if you need it
|
||||
extern int *curses_win32_global_user_colortab;
|
||||
extern const char *curses_win32_global_font_face_name;
|
||||
void init_user_colortab(win32CursesCtx *ctx); // if you're in a hurry, otherwise blinking cursor detects
|
||||
|
||||
void curses_setWindowContext(HWND hwnd, win32CursesCtx *ctx);
|
||||
void curses_unregisterChildClass(HINSTANCE hInstance);
|
||||
void curses_registerChildClass(HINSTANCE hInstance);
|
||||
HWND curses_CreateWindow(HINSTANCE hInstance, win32CursesCtx *ctx, const char *title);
|
||||
|
||||
|
||||
void __addnstr(win32CursesCtx *inst, const char *str,int n);
|
||||
void __addnstr_w(win32CursesCtx *inst, const wchar_t *str,int n);
|
||||
void __move(win32CursesCtx *inst, int y, int x, int noupdest);
|
||||
static inline void __addch(win32CursesCtx *inst, wchar_t c) { __addnstr_w(inst,&c,1); }
|
||||
static inline void __mvaddnstr(win32CursesCtx *inst, int x, int y, const char *str, int n) { __move(inst,x,y,1); __addnstr(inst,str,n); }
|
||||
static inline void __mvaddnstr_w(win32CursesCtx *inst, int x, int y, const wchar_t *str, int n) { __move(inst,x,y,1); __addnstr_w(inst,str,n); }
|
||||
|
||||
|
||||
void __clrtoeol(win32CursesCtx *inst);
|
||||
void __initscr(win32CursesCtx *inst);
|
||||
void __endwin(win32CursesCtx *inst);
|
||||
void __curses_erase(win32CursesCtx *inst);
|
||||
void __curses_invalidatefull(win32CursesCtx *inst, bool finish); // use around a block with a lot of drawing to prevent excessive invalidaterects
|
||||
|
||||
int curses_getch(win32CursesCtx *inst);
|
||||
|
||||
#if defined(_WIN32) || defined(MAC_NATIVE) || defined(FORCE_WIN32_CURSES)
|
||||
#define getch() curses_getch(CURSES_INSTANCE)
|
||||
#define erase() curses_erase(CURSES_INSTANCE)
|
||||
#endif
|
||||
|
||||
|
||||
#define wrefresh(x)
|
||||
#define cbreak()
|
||||
#define noecho()
|
||||
#define nonl()
|
||||
#define intrflush(x,y)
|
||||
#define keypad(x,y)
|
||||
#define nodelay(x,y)
|
||||
#define raw()
|
||||
#define refresh()
|
||||
#define sync()
|
||||
|
||||
|
||||
|
||||
#define COLOR_WHITE RGB(192,192,192)
|
||||
#define COLOR_BLACK RGB(0,0,0)
|
||||
#define COLOR_BLUE RGB(0,0,192)
|
||||
#define COLOR_RED RGB(192,0,0)
|
||||
#define COLOR_CYAN RGB(0,192,192)
|
||||
#define COLOR_BLUE_DIM RGB(0,0,56)
|
||||
#define COLOR_RED_DIM RGB(56,0,0)
|
||||
#define COLOR_CYAN_DIM RGB(0,56,56)
|
||||
|
||||
#define ERR -1
|
||||
|
||||
enum
|
||||
{
|
||||
KEY_DOWN=4096,
|
||||
KEY_UP,
|
||||
KEY_PPAGE,
|
||||
KEY_NPAGE,
|
||||
KEY_RIGHT,
|
||||
KEY_LEFT,
|
||||
KEY_HOME,
|
||||
KEY_END,
|
||||
KEY_IC,
|
||||
KEY_DC,
|
||||
KEY_F1,
|
||||
KEY_F2,
|
||||
KEY_F3,
|
||||
KEY_F4,
|
||||
KEY_F5,
|
||||
KEY_F6,
|
||||
KEY_F7,
|
||||
KEY_F8,
|
||||
KEY_F9,
|
||||
KEY_F10,
|
||||
KEY_F11,
|
||||
KEY_F12,
|
||||
};
|
||||
|
||||
#define KEY_BACKSPACE '\b'
|
||||
|
||||
#define KEY_F(x) (KEY_F1 + (x) - 1)
|
||||
|
||||
|
||||
void __init_pair(win32CursesCtx *ctx, int p, int b, int f);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
3105
oversampling/WDL/win32_curses/curses_editor.cpp
Normal file
3105
oversampling/WDL/win32_curses/curses_editor.cpp
Normal file
File diff suppressed because it is too large
Load Diff
238
oversampling/WDL/win32_curses/curses_editor.h
Normal file
238
oversampling/WDL/win32_curses/curses_editor.h
Normal file
@@ -0,0 +1,238 @@
|
||||
#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
|
||||
954
oversampling/WDL/win32_curses/curses_win32.cpp
Normal file
954
oversampling/WDL/win32_curses/curses_win32.cpp
Normal file
@@ -0,0 +1,954 @@
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include "../swell/swell.h"
|
||||
#endif
|
||||
#define CURSES_INSTANCE ___ERRROR_____
|
||||
|
||||
#include "../wdltypes.h"
|
||||
#include "../wdlutf8.h"
|
||||
|
||||
#include "curses.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define CURSOR_BLINK_TIMER_MS 400
|
||||
#define CURSOR_BLINK_TIMER 2
|
||||
#define CURSOR_BLINK_TIMER_ZEROEVERY 3
|
||||
|
||||
#define WIN32CURSES_CLASS_NAME "WDLCursesWindow"
|
||||
#define LWIN32CURSES_CLASS_NAME L"WDLCursesWindow"
|
||||
|
||||
static void doFontCalc(win32CursesCtx*, HDC);
|
||||
static void reInitializeContext(win32CursesCtx *ctx);
|
||||
|
||||
static void m_InvalidateArea(win32CursesCtx *ctx, int sx, int sy, int ex, int ey)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
doFontCalc(ctx,NULL);
|
||||
|
||||
if (!ctx->m_hwnd || (ctx->need_redraw&4)) return;
|
||||
|
||||
RECT r;
|
||||
r.left=sx*ctx->m_font_w;
|
||||
r.top=sy*ctx->m_font_h;
|
||||
r.right=ex*ctx->m_font_w;
|
||||
r.bottom=ey*ctx->m_font_h;
|
||||
InvalidateRect(ctx->m_hwnd,&r,FALSE);
|
||||
}
|
||||
|
||||
void __curses_invalidatefull(win32CursesCtx *inst, bool finish)
|
||||
{
|
||||
if (inst && inst->m_hwnd)
|
||||
{
|
||||
if (finish)
|
||||
{
|
||||
if (inst->need_redraw&4)
|
||||
{
|
||||
inst->need_redraw&=~4;
|
||||
InvalidateRect(inst->m_hwnd,NULL,FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
inst->need_redraw|=4;
|
||||
}
|
||||
}
|
||||
|
||||
void __addnstr(win32CursesCtx *ctx, const char *str,int n)
|
||||
{
|
||||
if (!ctx||n==0) return;
|
||||
|
||||
const int sx=ctx->m_cursor_x, sy=ctx->m_cursor_y, cols=ctx->cols;
|
||||
if (!ctx->m_framebuffer || sy < 0 || sy >= ctx->lines || sx < 0 || sx >= cols) return;
|
||||
win32CursesFB *p=ctx->m_framebuffer + (sx + sy*cols);
|
||||
|
||||
const unsigned char attr = ctx->m_cur_attr;
|
||||
while (n && *str)
|
||||
{
|
||||
int c,sz=wdl_utf8_parsechar(str,&c);
|
||||
p->c=(wchar_t)c;
|
||||
p->attr=attr;
|
||||
p++;
|
||||
str+=sz;
|
||||
if (n > 0 && (n-=sz)<0) n = 0;
|
||||
|
||||
if (++ctx->m_cursor_x >= cols) break;
|
||||
}
|
||||
m_InvalidateArea(ctx,sx,sy,sy < ctx->m_cursor_y ? cols : ctx->m_cursor_x+1,ctx->m_cursor_y+1);
|
||||
}
|
||||
|
||||
void __addnstr_w(win32CursesCtx *ctx, const wchar_t *str,int n)
|
||||
{
|
||||
if (!ctx||n==0) return;
|
||||
|
||||
const int sx=ctx->m_cursor_x, sy=ctx->m_cursor_y, cols=ctx->cols;
|
||||
if (!ctx->m_framebuffer || sy < 0 || sy >= ctx->lines || sx < 0 || sx >= cols) return;
|
||||
win32CursesFB *p=ctx->m_framebuffer + (sx + sy*cols);
|
||||
|
||||
const unsigned char attr = ctx->m_cur_attr;
|
||||
while (n-- && *str)
|
||||
{
|
||||
p->c=*str++;
|
||||
p->attr=attr;
|
||||
p++;
|
||||
if (++ctx->m_cursor_x >= cols) break;
|
||||
}
|
||||
m_InvalidateArea(ctx,sx,sy,sy < ctx->m_cursor_y ? cols : ctx->m_cursor_x+1,ctx->m_cursor_y+1);
|
||||
}
|
||||
|
||||
void __clrtoeol(win32CursesCtx *ctx)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
if (ctx->m_cursor_x<0)ctx->m_cursor_x=0;
|
||||
int n = ctx->cols - ctx->m_cursor_x;
|
||||
if (!ctx->m_framebuffer || ctx->m_cursor_y < 0 || ctx->m_cursor_y >= ctx->lines || n < 1) return;
|
||||
win32CursesFB *p=ctx->m_framebuffer + (ctx->m_cursor_x + ctx->m_cursor_y*ctx->cols);
|
||||
int sx=ctx->m_cursor_x;
|
||||
while (n--)
|
||||
{
|
||||
p->c=0;
|
||||
p->attr=ctx->m_cur_erase_attr;
|
||||
p++;
|
||||
}
|
||||
m_InvalidateArea(ctx,sx,ctx->m_cursor_y,ctx->cols,ctx->m_cursor_y+1);
|
||||
}
|
||||
|
||||
void __curses_erase(win32CursesCtx *ctx)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
ctx->m_cur_attr=0;
|
||||
ctx->m_cur_erase_attr=0;
|
||||
if (ctx->m_framebuffer) memset(ctx->m_framebuffer,0,ctx->cols*ctx->lines*sizeof(*ctx->m_framebuffer));
|
||||
ctx->m_cursor_x=0;
|
||||
ctx->m_cursor_y=0;
|
||||
m_InvalidateArea(ctx,0,0,ctx->cols,ctx->lines);
|
||||
}
|
||||
|
||||
void __move(win32CursesCtx *ctx, int y, int x, int noupdest)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
m_InvalidateArea(ctx,ctx->m_cursor_x,ctx->m_cursor_y,ctx->m_cursor_x+1,ctx->m_cursor_y+1);
|
||||
ctx->m_cursor_x=wdl_max(x,0);
|
||||
ctx->m_cursor_y=wdl_max(y,0);
|
||||
if (!noupdest) m_InvalidateArea(ctx,ctx->m_cursor_x,ctx->m_cursor_y,ctx->m_cursor_x+1,ctx->m_cursor_y+1);
|
||||
}
|
||||
|
||||
|
||||
void __init_pair(win32CursesCtx *ctx, int pair, int fcolor, int bcolor)
|
||||
{
|
||||
if (!ctx || pair < 0 || pair >= COLOR_PAIRS) return;
|
||||
|
||||
pair=COLOR_PAIR(pair);
|
||||
fcolor &= RGB(255,255,255);
|
||||
bcolor &= RGB(255,255,255);
|
||||
|
||||
ctx->colortab[pair][0]=fcolor;
|
||||
ctx->colortab[pair][1]=bcolor;
|
||||
|
||||
if (fcolor & 0xff) fcolor|=0xff;
|
||||
if (fcolor & 0xff00) fcolor|=0xff00;
|
||||
if (fcolor & 0xff0000) fcolor|=0xff0000;
|
||||
ctx->colortab[pair|A_BOLD][0]=fcolor;
|
||||
ctx->colortab[pair|A_BOLD][1]=bcolor;
|
||||
}
|
||||
|
||||
int *curses_win32_global_user_colortab;
|
||||
const char *curses_win32_global_font_face_name;
|
||||
|
||||
static LRESULT xlateKey(int msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (msg == WM_KEYDOWN)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
if (lParam & FVIRTKEY)
|
||||
#endif
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_HOME: return KEY_HOME;
|
||||
case VK_UP: return KEY_UP;
|
||||
case VK_PRIOR: return KEY_PPAGE;
|
||||
case VK_LEFT: return KEY_LEFT;
|
||||
case VK_RIGHT: return KEY_RIGHT;
|
||||
case VK_END: return KEY_END;
|
||||
case VK_DOWN: return KEY_DOWN;
|
||||
case VK_NEXT: return KEY_NPAGE;
|
||||
case VK_INSERT: return KEY_IC;
|
||||
case VK_DELETE: return KEY_DC;
|
||||
case VK_F1: return KEY_F1;
|
||||
case VK_F2: return KEY_F2;
|
||||
case VK_F3: return KEY_F3;
|
||||
case VK_F4: return KEY_F4;
|
||||
case VK_F5: return KEY_F5;
|
||||
case VK_F6: return KEY_F6;
|
||||
case VK_F7: return KEY_F7;
|
||||
case VK_F8: return KEY_F8;
|
||||
case VK_F9: return KEY_F9;
|
||||
case VK_F10: return KEY_F10;
|
||||
case VK_F11: return KEY_F11;
|
||||
case VK_F12: return KEY_F12;
|
||||
#ifndef _WIN32
|
||||
case VK_SUBTRACT: return '-'; // numpad -
|
||||
case VK_ADD: return '+';
|
||||
case VK_MULTIPLY: return '*';
|
||||
case VK_DIVIDE: return '/';
|
||||
case VK_DECIMAL: return '.';
|
||||
case VK_NUMPAD0: return '0';
|
||||
case VK_NUMPAD1: return '1';
|
||||
case VK_NUMPAD2: return '2';
|
||||
case VK_NUMPAD3: return '3';
|
||||
case VK_NUMPAD4: return '4';
|
||||
case VK_NUMPAD5: return '5';
|
||||
case VK_NUMPAD6: return '6';
|
||||
case VK_NUMPAD7: return '7';
|
||||
case VK_NUMPAD8: return '8';
|
||||
case VK_NUMPAD9: return '9';
|
||||
case (32768|VK_RETURN): return VK_RETURN;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch (wParam)
|
||||
{
|
||||
case VK_RETURN: case VK_BACK: case VK_TAB: case VK_ESCAPE: return wParam;
|
||||
case VK_CONTROL: break;
|
||||
|
||||
default:
|
||||
if ((GetAsyncKeyState(VK_CONTROL)&0x8000) && !(GetAsyncKeyState(VK_MENU)&0x8000))
|
||||
{
|
||||
if (wParam>='a' && wParam<='z')
|
||||
{
|
||||
wParam += 1-'a';
|
||||
return wParam;
|
||||
}
|
||||
if (wParam>='A' && wParam<='Z')
|
||||
{
|
||||
wParam += 1-'A';
|
||||
return wParam;
|
||||
}
|
||||
if ((wParam&~0x80) == '[') return 27;
|
||||
if ((wParam&~0x80) == ']') return 29;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (msg == WM_CHAR)
|
||||
{
|
||||
if(wParam>=32) return wParam;
|
||||
}
|
||||
#else
|
||||
//osx/linux
|
||||
if (wParam >= 32)
|
||||
{
|
||||
if (!(GetAsyncKeyState(VK_SHIFT)&0x8000))
|
||||
{
|
||||
if (wParam>='A' && wParam<='Z')
|
||||
{
|
||||
if ((GetAsyncKeyState(VK_LWIN)&0x8000)) wParam -= 'A'-1;
|
||||
else
|
||||
wParam += 'a'-'A';
|
||||
}
|
||||
}
|
||||
return wParam;
|
||||
}
|
||||
|
||||
#endif
|
||||
return ERR;
|
||||
}
|
||||
|
||||
|
||||
static void m_reinit_framebuffer(win32CursesCtx *ctx)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
doFontCalc(ctx,NULL);
|
||||
RECT r;
|
||||
|
||||
GetClientRect(ctx->m_hwnd,&r);
|
||||
|
||||
ctx->lines=r.bottom / ctx->m_font_h;
|
||||
ctx->cols=r.right / ctx->m_font_w;
|
||||
if (ctx->lines<1) ctx->lines=1;
|
||||
if (ctx->cols<1) ctx->cols=1;
|
||||
ctx->m_cursor_x=0;
|
||||
ctx->m_cursor_y=0;
|
||||
free(ctx->m_framebuffer);
|
||||
ctx->m_framebuffer=(win32CursesFB *)malloc(sizeof(win32CursesFB)*ctx->lines*ctx->cols);
|
||||
if (ctx->m_framebuffer) memset(ctx->m_framebuffer, 0,sizeof(win32CursesFB)*ctx->lines*ctx->cols);
|
||||
|
||||
const int *tab = ctx->user_colortab ? ctx->user_colortab : curses_win32_global_user_colortab;
|
||||
if (tab)
|
||||
{
|
||||
ctx->user_colortab_lastfirstval=tab[0];
|
||||
for (int x=0;x<COLOR_PAIRS;x++) __init_pair(ctx,x,tab[x*2],tab[x*2+1]);
|
||||
}
|
||||
}
|
||||
#ifndef WM_MOUSEWHEEL
|
||||
#define WM_MOUSEWHEEL 0x20A
|
||||
#endif
|
||||
|
||||
LRESULT CALLBACK cursesWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
win32CursesCtx *ctx = (win32CursesCtx*)GetWindowLongPtr(hwnd,GWLP_USERDATA);
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
static int Scroll_Message;
|
||||
if (!Scroll_Message)
|
||||
{
|
||||
Scroll_Message = (int)RegisterWindowMessage("MSWHEEL_ROLLMSG");
|
||||
if (!Scroll_Message) Scroll_Message=-1;
|
||||
}
|
||||
if (Scroll_Message > 0 && uMsg == (UINT)Scroll_Message)
|
||||
{
|
||||
uMsg=WM_MOUSEWHEEL;
|
||||
wParam<<=16;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx) switch (uMsg)
|
||||
{
|
||||
case WM_DESTROY:
|
||||
ctx->m_hwnd=0;
|
||||
return 0;
|
||||
case WM_CHAR:
|
||||
case WM_KEYDOWN:
|
||||
|
||||
#ifdef __APPLE__
|
||||
{
|
||||
int f=0;
|
||||
wParam = SWELL_MacKeyToWindowsKeyEx(NULL,&f,1);
|
||||
lParam=f;
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
const int a=(int)xlateKey(uMsg,wParam,lParam);
|
||||
if (a != ERR)
|
||||
{
|
||||
const int qsize = sizeof(ctx->m_kb_queue)/sizeof(ctx->m_kb_queue[0]);
|
||||
if (ctx->m_kb_queue_valid>=qsize) // queue full, dump an old event!
|
||||
{
|
||||
ctx->m_kb_queue_valid--;
|
||||
ctx->m_kb_queue_pos++;
|
||||
}
|
||||
|
||||
ctx->m_kb_queue[(ctx->m_kb_queue_pos + ctx->m_kb_queue_valid++) & (qsize-1)] = a;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_KEYUP:
|
||||
return 0;
|
||||
case WM_GETMINMAXINFO:
|
||||
{
|
||||
LPMINMAXINFO p=(LPMINMAXINFO)lParam;
|
||||
p->ptMinTrackSize.x = 160;
|
||||
p->ptMinTrackSize.y = 120;
|
||||
}
|
||||
return 0;
|
||||
case WM_SIZE:
|
||||
if (wParam != SIZE_MINIMIZED)
|
||||
{
|
||||
m_reinit_framebuffer(ctx);
|
||||
if (ctx->do_update) ctx->do_update(ctx);
|
||||
else ctx->need_redraw|=1;
|
||||
}
|
||||
return 0;
|
||||
case WM_RBUTTONDOWN:
|
||||
case WM_LBUTTONDOWN:
|
||||
SetFocus(hwnd);
|
||||
WDL_FALLTHROUGH;
|
||||
case WM_LBUTTONUP:
|
||||
case WM_RBUTTONUP:
|
||||
case WM_CAPTURECHANGED:
|
||||
case WM_MOUSEMOVE:
|
||||
case WM_MOUSEWHEEL:
|
||||
case WM_LBUTTONDBLCLK:
|
||||
case WM_RBUTTONDBLCLK:
|
||||
case WM_MBUTTONDBLCLK:
|
||||
if (ctx && ctx->fontsize_ptr && uMsg == WM_MOUSEWHEEL && (GetAsyncKeyState(VK_CONTROL)&0x8000))
|
||||
{
|
||||
int a = (int)(short)HIWORD(wParam);
|
||||
if (a<0 && *ctx->fontsize_ptr > 4) (*ctx->fontsize_ptr)--;
|
||||
else if (a>=0 && *ctx->fontsize_ptr < 64) (*ctx->fontsize_ptr)++;
|
||||
else return 1;
|
||||
|
||||
if (ctx->mOurFont)
|
||||
{
|
||||
DeleteObject(ctx->mOurFont);
|
||||
ctx->mOurFont=NULL;
|
||||
}
|
||||
reInitializeContext(ctx);
|
||||
m_reinit_framebuffer(ctx);
|
||||
if (ctx->do_update) ctx->do_update(ctx);
|
||||
else ctx->need_redraw|=1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (ctx && ctx->onMouseMessage) return ctx->onMouseMessage(ctx->user_data,hwnd,uMsg,wParam,lParam);
|
||||
return 0;
|
||||
|
||||
case WM_SETCURSOR:
|
||||
if (ctx->m_font_w && ctx->m_font_h)
|
||||
{
|
||||
POINT p;
|
||||
GetCursorPos(&p);
|
||||
ScreenToClient(hwnd, &p);
|
||||
p.x /= ctx->m_font_w;
|
||||
p.y /= ctx->m_font_h;
|
||||
|
||||
const int topmarg=ctx->scrollbar_topmargin;
|
||||
const int bottmarg=ctx->scrollbar_botmargin;
|
||||
int paney[2] = { topmarg, ctx->div_y+topmarg+1 };
|
||||
int paneh[2] = { ctx->div_y, ctx->lines-ctx->div_y-topmarg-bottmarg-1 };
|
||||
bool has_panes=(ctx->div_y < ctx->lines-topmarg-bottmarg-1);
|
||||
int scrollw[2] = { ctx->cols-ctx->drew_scrollbar[0], ctx->cols-ctx->drew_scrollbar[1] };
|
||||
|
||||
if (has_panes && p.y >= ctx->div_y+1 && p.y < ctx->div_y+2) SetCursor(LoadCursor(NULL, IDC_SIZENS));
|
||||
else if (p.y < 1 || p.y >= ctx->lines-1) SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
else if (p.y >= paney[0] && p.y < paney[0]+paneh[0] && p.x >= scrollw[0]) SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
else if (p.y >= paney[1] && p.y < paney[1]+paneh[1] && p.x >= scrollw[1]) SetCursor(LoadCursor(NULL, IDC_ARROW));
|
||||
else SetCursor(LoadCursor(NULL, IDC_IBEAM));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
#ifdef _WIN32
|
||||
case WM_GETDLGCODE:
|
||||
if (GetParent(hwnd))
|
||||
{
|
||||
return DLGC_WANTALLKEYS;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
case WM_TIMER:
|
||||
if (wParam==CURSOR_BLINK_TIMER && ctx)
|
||||
{
|
||||
const char la = ctx->cursor_state;
|
||||
ctx->cursor_state = (ctx->cursor_state+1)%CURSOR_BLINK_TIMER_ZEROEVERY;
|
||||
if (!ctx->cursor_state && GetFocus() != hwnd) ctx->cursor_state=1;
|
||||
|
||||
const int *tab = ctx->user_colortab ? ctx->user_colortab : curses_win32_global_user_colortab;
|
||||
if (tab && tab[0] != ctx->user_colortab_lastfirstval)
|
||||
{
|
||||
m_reinit_framebuffer(ctx);
|
||||
if (ctx->do_update) ctx->do_update(ctx);
|
||||
else ctx->need_redraw|=1;
|
||||
}
|
||||
else if (!!ctx->cursor_state != !!la)
|
||||
{
|
||||
__move(ctx,ctx->m_cursor_y,ctx->m_cursor_x,1);// refresh cursor
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
case WM_CREATE:
|
||||
|
||||
// this only is called on osx or from standalone, it seems, since on win32 ctx isnt set up yet
|
||||
ctx->m_hwnd=hwnd;
|
||||
#ifndef _WIN32
|
||||
m_reinit_framebuffer(ctx);
|
||||
ctx->need_redraw|=1;
|
||||
#endif
|
||||
SetTimer(hwnd,CURSOR_BLINK_TIMER,CURSOR_BLINK_TIMER_MS,NULL);
|
||||
return 0;
|
||||
case WM_ERASEBKGND:
|
||||
return 1;
|
||||
case WM_PAINT:
|
||||
{
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
HDC hdc=BeginPaint(hwnd,&ps);
|
||||
if (hdc)
|
||||
{
|
||||
const int topmarg=ctx->scrollbar_topmargin;
|
||||
const int bottmarg=ctx->scrollbar_botmargin;
|
||||
int paney[2] = { topmarg, ctx->div_y+topmarg+1 };
|
||||
int paneh[2] = { ctx->div_y, ctx->lines-ctx->div_y-topmarg-bottmarg-1 };
|
||||
bool has_panes=(ctx->div_y < ctx->lines-topmarg-bottmarg-1);
|
||||
if (!has_panes) paneh[0]++;
|
||||
|
||||
ctx->drew_scrollbar[0]=ctx->drew_scrollbar[1]=0;
|
||||
if (ctx->want_scrollbar > 0)
|
||||
{
|
||||
RECT cr;
|
||||
GetClientRect(hwnd, &cr);
|
||||
double cf=(double)cr.right/(double)ctx->m_font_w-(double)ctx->cols;
|
||||
int ws=ctx->want_scrollbar;
|
||||
if (cf < 0.5) ++ws;
|
||||
|
||||
int i;
|
||||
for (i=0; i < 2; ++i)
|
||||
{
|
||||
ctx->scroll_y[i]=ctx->scroll_h[i]=0;
|
||||
if (paneh[i] > 0 && ctx->tot_y > paneh[i])
|
||||
{
|
||||
ctx->drew_scrollbar[i]=ws;
|
||||
int ey=paneh[i]*ctx->m_font_h;
|
||||
ctx->scroll_h[i]=ey*paneh[i]/ctx->tot_y;
|
||||
if (ctx->scroll_h[i] < ctx->m_font_h) ctx->scroll_h[i]=ctx->m_font_h;
|
||||
ctx->scroll_y[i]=(ey-ctx->scroll_h[i])*ctx->offs_y[i]/(ctx->tot_y-paneh[i]);
|
||||
if (ctx->scroll_y[i] < 0) ctx->scroll_y[i]=0;
|
||||
if (ctx->scroll_y[i] > ey-ctx->scroll_h[i]) ctx->scroll_y[i]=ey-ctx->scroll_h[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RECT r = ps.rcPaint;
|
||||
doFontCalc(ctx,ps.hdc);
|
||||
|
||||
HGDIOBJ oldf=SelectObject(hdc,ctx->mOurFont);
|
||||
int y,ypos;
|
||||
int lattr=-1;
|
||||
#ifdef _WIN32
|
||||
SetTextAlign(hdc,TA_TOP|TA_LEFT);
|
||||
#endif
|
||||
const win32CursesFB *ptr=(const win32CursesFB*)ctx->m_framebuffer;
|
||||
RECT updr=r;
|
||||
|
||||
r.left /= ctx->m_font_w;
|
||||
r.top /= ctx->m_font_h;
|
||||
r.bottom += ctx->m_font_h-1;
|
||||
r.bottom /= ctx->m_font_h;
|
||||
r.right += ctx->m_font_w-1;
|
||||
r.right /= ctx->m_font_w;
|
||||
|
||||
if (r.top < 0) r.top=0;
|
||||
if (r.bottom > ctx->lines) r.bottom=ctx->lines;
|
||||
if (r.left < 0) r.left=0;
|
||||
if (r.right > ctx->cols) r.right=ctx->cols;
|
||||
|
||||
ypos = r.top * ctx->m_font_h;
|
||||
ptr += (r.top * ctx->cols);
|
||||
|
||||
|
||||
HBRUSH bgbrushes[COLOR_PAIRS << NUM_ATTRBITS];
|
||||
for(y=0;y<sizeof(bgbrushes)/sizeof(bgbrushes[0]);y++) bgbrushes[y] = CreateSolidBrush(ctx->colortab[y][1]);
|
||||
|
||||
char cstate=ctx->cursor_state;
|
||||
if (ctx->m_cursor_y != ctx->cursor_state_ly || ctx->m_cursor_x != ctx->cursor_state_lx)
|
||||
{
|
||||
ctx->cursor_state_lx=ctx->m_cursor_x;
|
||||
ctx->cursor_state_ly=ctx->m_cursor_y;
|
||||
ctx->cursor_state=0;
|
||||
cstate=1;
|
||||
}
|
||||
|
||||
if (ctx->m_framebuffer) for (y = r.top; y < r.bottom; y ++, ypos+=ctx->m_font_h, ptr += ctx->cols)
|
||||
{
|
||||
int x = r.left,xpos = r.left * ctx->m_font_w;
|
||||
|
||||
const win32CursesFB *p = ptr + r.left;
|
||||
|
||||
int defer_blanks=0;
|
||||
|
||||
int right=r.right;
|
||||
if (y >= paney[0] && y < paney[0]+paneh[0])
|
||||
{
|
||||
right=wdl_min(right, ctx->cols-ctx->drew_scrollbar[0]);
|
||||
}
|
||||
else if (y >= paney[1] && y < paney[1]+paneh[1])
|
||||
{
|
||||
right=wdl_min(right, ctx->cols-ctx->drew_scrollbar[1]);
|
||||
}
|
||||
|
||||
for (;; x ++, xpos+=ctx->m_font_w, p ++)
|
||||
{
|
||||
wchar_t c=' ';
|
||||
int attr=0;
|
||||
|
||||
if (x < right)
|
||||
{
|
||||
c=p->c;
|
||||
attr=p->attr;
|
||||
}
|
||||
|
||||
const bool isCursor = cstate && y == ctx->m_cursor_y && x == ctx->m_cursor_x;
|
||||
const bool isNotBlank = c>=128 || (isprint(c) && !isspace(c));
|
||||
|
||||
if (defer_blanks > 0 && (isNotBlank || isCursor || attr != lattr || x>=right))
|
||||
{
|
||||
RECT tr={xpos - defer_blanks*ctx->m_font_w,ypos,xpos,ypos+ctx->m_font_h};
|
||||
FillRect(hdc,&tr,bgbrushes[lattr&((COLOR_PAIRS << NUM_ATTRBITS)-1)]);
|
||||
defer_blanks=0;
|
||||
}
|
||||
|
||||
if (x>=right) break;
|
||||
|
||||
if (isCursor && ctx->cursor_type == WIN32_CURSES_CURSOR_TYPE_BLOCK)
|
||||
{
|
||||
SetTextColor(hdc,ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][1]);
|
||||
SetBkColor(hdc,ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][0]);
|
||||
lattr = -1;
|
||||
}
|
||||
else
|
||||
if (attr != lattr)
|
||||
{
|
||||
SetTextColor(hdc,ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][0]);
|
||||
SetBkColor(hdc,ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][1]);
|
||||
lattr=attr;
|
||||
}
|
||||
|
||||
if (isNotBlank||isCursor)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
int txpos = xpos;
|
||||
TextOutW(hdc,txpos,ypos,isNotBlank ? &c : L" ",1);
|
||||
#else
|
||||
const int max_charw = ctx->m_font_w, max_charh = ctx->m_font_h;
|
||||
RECT tr={xpos,ypos,xpos+max_charw, ypos+max_charh};
|
||||
HBRUSH br=bgbrushes[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)];
|
||||
if (isCursor && ctx->cursor_type == WIN32_CURSES_CURSOR_TYPE_BLOCK)
|
||||
{
|
||||
br = CreateSolidBrush(ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][0]);
|
||||
FillRect(hdc,&tr,br);
|
||||
DeleteObject(br);
|
||||
}
|
||||
else
|
||||
{
|
||||
FillRect(hdc,&tr,br);
|
||||
}
|
||||
char tmp[16];
|
||||
if (c >= 128)
|
||||
{
|
||||
WDL_MakeUTFChar(tmp,c,sizeof(tmp));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp[0]=isNotBlank ? (char)c : ' ';
|
||||
tmp[1]=0;
|
||||
}
|
||||
DrawText(hdc,tmp,-1,&tr,DT_LEFT|DT_TOP|DT_NOPREFIX|DT_NOCLIP);
|
||||
#endif
|
||||
|
||||
if (isCursor && ctx->cursor_type != WIN32_CURSES_CURSOR_TYPE_BLOCK)
|
||||
{
|
||||
RECT r={xpos,ypos,xpos+2,ypos+ctx->m_font_h};
|
||||
if (ctx->cursor_type == WIN32_CURSES_CURSOR_TYPE_HORZBAR)
|
||||
{
|
||||
RECT tr={xpos,ypos+ctx->m_font_h-2,xpos+ctx->m_font_w,ypos+ctx->m_font_h};
|
||||
r=tr;
|
||||
}
|
||||
HBRUSH br=CreateSolidBrush(ctx->colortab[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)][0]);
|
||||
FillRect(hdc,&r,br);
|
||||
DeleteObject(br);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
defer_blanks++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ex=ctx->cols*ctx->m_font_w;
|
||||
int ey=ctx->lines*ctx->m_font_h;
|
||||
|
||||
int anyscrollw=wdl_max(ctx->drew_scrollbar[0], ctx->drew_scrollbar[1]);
|
||||
if (anyscrollw && updr.right >= ex-anyscrollw*ctx->m_font_w)
|
||||
{
|
||||
HBRUSH sb1=CreateSolidBrush(RGB(128,128,128));
|
||||
HBRUSH sb2=CreateSolidBrush(RGB(96, 96, 96));
|
||||
int i;
|
||||
for (i=0; i < 2; ++i)
|
||||
{
|
||||
if (ctx->drew_scrollbar[i])
|
||||
{
|
||||
int scrolly=paney[i]*ctx->m_font_h+ctx->scroll_y[i];
|
||||
int scrollh=ctx->scroll_h[i];
|
||||
RECT tr = { ex-ctx->drew_scrollbar[i]*ctx->m_font_w, paney[i]*ctx->m_font_h, updr.right, wdl_min(scrolly, updr.bottom) };
|
||||
if (tr.bottom > tr.top) FillRect(hdc, &tr, sb1);
|
||||
tr.top=wdl_max(updr.top, scrolly);
|
||||
tr.bottom=wdl_min(updr.bottom, scrolly+scrollh);
|
||||
if (tr.bottom > tr.top) FillRect(hdc, &tr, sb2);
|
||||
tr.top=wdl_max(updr.top,scrolly+scrollh);
|
||||
tr.bottom=(paney[i]+paneh[i])*ctx->m_font_h;
|
||||
if (tr.bottom > tr.top) FillRect(hdc, &tr, sb1);
|
||||
}
|
||||
}
|
||||
DeleteObject(sb1);
|
||||
DeleteObject(sb2);
|
||||
}
|
||||
|
||||
ex -= ctx->m_font_w;
|
||||
if (updr.right >= ex)
|
||||
{
|
||||
// draw the scrollbars if they haven't been already drawn
|
||||
if (!ctx->drew_scrollbar[0] && updr.bottom > paney[0]*ctx->m_font_h && updr.top < (paney[0]+paneh[0])*ctx->m_font_h)
|
||||
{
|
||||
RECT tr = { ex, paney[0]*ctx->m_font_h, updr.right, (paney[0]+paneh[0])*ctx->m_font_h };
|
||||
FillRect(hdc, &tr, bgbrushes[0]);
|
||||
}
|
||||
if (!ctx->drew_scrollbar[1] && updr.bottom > paney[1]*ctx->m_font_h && updr.top < (paney[1]+paneh[1])*ctx->m_font_h)
|
||||
{
|
||||
RECT tr = { ex, paney[1]*ctx->m_font_h, updr.right, (paney[1]+paneh[1])*ctx->m_font_h };
|
||||
FillRect(hdc, &tr, bgbrushes[0]);
|
||||
}
|
||||
|
||||
// draw line endings of special areas
|
||||
|
||||
const int div1a = has_panes ? (paney[0]+paneh[0]) : 0;
|
||||
const int div1b = has_panes ? paney[1] : 0;
|
||||
|
||||
int y;
|
||||
const int bm1 = ctx->lines-bottmarg;
|
||||
const int fonth = ctx->m_font_h;
|
||||
for (y = r.top; y < r.bottom; y ++)
|
||||
{
|
||||
if (y < topmarg || y>=bm1 || (y<div1b && y >= div1a))
|
||||
{
|
||||
const int attr = ctx->m_framebuffer ? ctx->m_framebuffer[(y+1) * ctx->cols - 1].attr : 0; // last attribute of line
|
||||
|
||||
const int yp = y * fonth;
|
||||
RECT tr = { wdl_max(ex,updr.left), wdl_max(yp,updr.top), updr.right, wdl_min(yp+fonth,updr.bottom) };
|
||||
FillRect(hdc, &tr, bgbrushes[attr&((COLOR_PAIRS << NUM_ATTRBITS)-1)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updr.bottom > ey)
|
||||
{
|
||||
RECT tr= { updr.left, wdl_max(ey,updr.top), updr.right, updr.bottom };
|
||||
FillRect(hdc, &tr, bgbrushes[2]);
|
||||
}
|
||||
|
||||
for(y=0;y<sizeof(bgbrushes)/sizeof(bgbrushes[0]);y++) DeleteObject(bgbrushes[y]);
|
||||
SelectObject(hdc,oldf);
|
||||
|
||||
EndPaint(hwnd,&ps);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
return DefWindowProcW(hwnd,uMsg,wParam,lParam);
|
||||
#else
|
||||
return DefWindowProc(hwnd,uMsg,wParam,lParam);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void doFontCalc(win32CursesCtx *ctx, HDC hdcIn)
|
||||
{
|
||||
if (!ctx || !ctx->m_hwnd || !(ctx->need_redraw&2)) return;
|
||||
|
||||
HDC hdc = hdcIn;
|
||||
if (!hdc) hdc = GetDC(ctx->m_hwnd);
|
||||
|
||||
if (!hdc) return;
|
||||
|
||||
ctx->need_redraw&=~2;
|
||||
|
||||
HGDIOBJ oldf=SelectObject(hdc,ctx->mOurFont);
|
||||
TEXTMETRIC tm;
|
||||
GetTextMetrics(hdc,&tm);
|
||||
ctx->m_font_h=tm.tmHeight;
|
||||
ctx->m_font_w=tm.tmAveCharWidth;
|
||||
SelectObject(hdc,oldf);
|
||||
|
||||
if (hdc != hdcIn) ReleaseDC(ctx->m_hwnd,hdc);
|
||||
|
||||
}
|
||||
|
||||
void reInitializeContext(win32CursesCtx *ctx)
|
||||
{
|
||||
if (!ctx) return;
|
||||
|
||||
if (!ctx->mOurFont) ctx->mOurFont = CreateFont(
|
||||
ctx->fontsize_ptr ? *ctx->fontsize_ptr :
|
||||
#ifdef _WIN32
|
||||
16,
|
||||
#else
|
||||
14,
|
||||
#endif
|
||||
0, // width
|
||||
0, // escapement
|
||||
0, // orientation
|
||||
#ifndef __APPLE__
|
||||
FW_NORMAL, // normal
|
||||
#else
|
||||
FW_BOLD,
|
||||
#endif
|
||||
FALSE, //italic
|
||||
FALSE, //undelrine
|
||||
FALSE, //strikeout
|
||||
ANSI_CHARSET,
|
||||
OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS,
|
||||
ANTIALIASED_QUALITY, //NONANTIALIASED_QUALITY,//DEFAULT_QUALITY,
|
||||
#ifdef _WIN32
|
||||
FF_MODERN,
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
curses_win32_global_font_face_name ? curses_win32_global_font_face_name :
|
||||
"Courier New");
|
||||
|
||||
ctx->need_redraw|=2;
|
||||
ctx->m_font_w=8;
|
||||
ctx->m_font_h=8;
|
||||
doFontCalc(ctx,NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void __initscr(win32CursesCtx *ctx)
|
||||
{
|
||||
#ifdef WDL_IS_FAKE_CURSES
|
||||
if (!curses_win32_global_user_colortab && (!ctx || !ctx->user_colortab))
|
||||
#endif
|
||||
{
|
||||
__init_pair(ctx,0,RGB(192,192,192),RGB(0,0,0));
|
||||
}
|
||||
}
|
||||
|
||||
void __endwin(win32CursesCtx *ctx)
|
||||
{
|
||||
if (ctx)
|
||||
{
|
||||
if (ctx->m_hwnd)
|
||||
curses_setWindowContext(ctx->m_hwnd,0);
|
||||
ctx->m_kb_queue_valid=0;
|
||||
ctx->m_hwnd=0;
|
||||
free(ctx->m_framebuffer);
|
||||
ctx->m_framebuffer=0;
|
||||
if (ctx->mOurFont) DeleteObject(ctx->mOurFont);
|
||||
ctx->mOurFont=0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int curses_getch(win32CursesCtx *ctx)
|
||||
{
|
||||
if (!ctx || !ctx->m_hwnd) return ERR;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (ctx->want_getch_runmsgpump>0)
|
||||
{
|
||||
MSG msg;
|
||||
if (ctx->want_getch_runmsgpump>1)
|
||||
{
|
||||
while(!ctx->m_kb_queue_valid && GetMessage(&msg,NULL,0,0))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
else while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
|
||||
{
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx->m_kb_queue_valid)
|
||||
{
|
||||
const int qsize = sizeof(ctx->m_kb_queue)/sizeof(ctx->m_kb_queue[0]);
|
||||
const int a = ctx->m_kb_queue[ctx->m_kb_queue_pos & (qsize-1)];
|
||||
ctx->m_kb_queue_pos++;
|
||||
ctx->m_kb_queue_valid--;
|
||||
return a;
|
||||
}
|
||||
|
||||
if (ctx->need_redraw&1)
|
||||
{
|
||||
ctx->need_redraw&=~1;
|
||||
InvalidateRect(ctx->m_hwnd,NULL,FALSE);
|
||||
return 'L'-'A'+1;
|
||||
}
|
||||
|
||||
return ERR;
|
||||
}
|
||||
|
||||
void curses_setWindowContext(HWND hwnd, win32CursesCtx *ctx)
|
||||
{
|
||||
SetWindowLongPtr(hwnd,GWLP_USERDATA,(INT_PTR)ctx);
|
||||
if (ctx)
|
||||
{
|
||||
ctx->m_hwnd=hwnd;
|
||||
ctx->m_kb_queue_valid=0;
|
||||
|
||||
free(ctx->m_framebuffer);
|
||||
ctx->m_framebuffer=0;
|
||||
|
||||
SetTimer(hwnd,CURSOR_BLINK_TIMER,CURSOR_BLINK_TIMER_MS,NULL);
|
||||
reInitializeContext(ctx);
|
||||
m_reinit_framebuffer(ctx);
|
||||
InvalidateRect(hwnd,NULL,FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static int m_regcnt;
|
||||
#endif
|
||||
|
||||
void curses_unregisterChildClass(HINSTANCE hInstance)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!--m_regcnt)
|
||||
UnregisterClass(WIN32CURSES_CLASS_NAME,hInstance);
|
||||
#endif
|
||||
}
|
||||
|
||||
void curses_registerChildClass(HINSTANCE hInstance)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!m_regcnt++)
|
||||
{
|
||||
WNDCLASSW wc={CS_DBLCLKS,};
|
||||
wc.lpfnWndProc = cursesWindowProc;
|
||||
wc.hInstance = hInstance;
|
||||
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
|
||||
wc.lpszClassName = LWIN32CURSES_CLASS_NAME;
|
||||
|
||||
RegisterClassW(&wc);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
HWND curses_ControlCreator(HWND parent, const char *cname, int idx, const char *classname, int style, int x, int y, int w, int h)
|
||||
{
|
||||
HWND hw=0;
|
||||
if (!strcmp(classname,WIN32CURSES_CLASS_NAME))
|
||||
{
|
||||
hw=CreateDialog(NULL,0,parent,(DLGPROC)cursesWindowProc);
|
||||
}
|
||||
|
||||
if (hw)
|
||||
{
|
||||
SWELL_SetClassName(hw,WIN32CURSES_CLASS_NAME);
|
||||
SetWindowLong(hw,GWL_ID,idx);
|
||||
SetWindowPos(hw,HWND_TOP,x,y,w,h,SWP_NOZORDER|SWP_NOACTIVATE);
|
||||
ShowWindow(hw,SW_SHOWNA);
|
||||
return hw;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
HWND curses_CreateWindow(HINSTANCE hInstance, win32CursesCtx *ctx, const char *title)
|
||||
{
|
||||
if (!ctx) return NULL;
|
||||
#ifdef _WIN32
|
||||
ctx->m_hwnd = CreateWindowEx(0,WIN32CURSES_CLASS_NAME, title,WS_CAPTION|WS_MAXIMIZEBOX|WS_MINIMIZEBOX|WS_SIZEBOX|WS_SYSMENU,
|
||||
CW_USEDEFAULT,CW_USEDEFAULT,640,480,
|
||||
NULL, NULL,hInstance,NULL);
|
||||
#else
|
||||
ctx->m_hwnd = CreateDialog(NULL,0,NULL,(DLGPROC)cursesWindowProc);
|
||||
|
||||
#endif
|
||||
if (ctx->m_hwnd)
|
||||
{
|
||||
curses_setWindowContext(ctx->m_hwnd,ctx);
|
||||
ShowWindow(ctx->m_hwnd,SW_SHOW);
|
||||
}
|
||||
return ctx->m_hwnd;
|
||||
}
|
||||
2405
oversampling/WDL/win32_curses/eel_edit.cpp
Normal file
2405
oversampling/WDL/win32_curses/eel_edit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
174
oversampling/WDL/win32_curses/eel_edit.h
Normal file
174
oversampling/WDL/win32_curses/eel_edit.h
Normal file
@@ -0,0 +1,174 @@
|
||||
#ifndef __WDL_EEL_EDITOR_H_
|
||||
#define __WDL_EEL_EDITOR_H_
|
||||
|
||||
#define STATE_BEFORE_CODE 255
|
||||
|
||||
#include "curses_editor.h"
|
||||
#include "../assocarray.h"
|
||||
|
||||
class suggested_matchlist {
|
||||
struct rec { char *val; int score, allocsz, mode; };
|
||||
WDL_TypedBuf<rec> m_list;
|
||||
int m_list_valid;
|
||||
public:
|
||||
|
||||
enum { MODE_FUNC=0, MODE_USERFUNC, MODE_VAR, MODE_REGVAR };
|
||||
|
||||
suggested_matchlist(int maxsz=80)
|
||||
{
|
||||
rec *list = m_list.ResizeOK(maxsz,false);
|
||||
if (list) memset(list,0,maxsz*sizeof(*list));
|
||||
}
|
||||
~suggested_matchlist()
|
||||
{
|
||||
for (int x = 0; x < m_list.GetSize(); x ++) free(m_list.Get()[x].val);
|
||||
}
|
||||
|
||||
int get_size() const { return m_list_valid; }
|
||||
const char *get(int idx, int *mode=NULL, int *score=NULL) const {
|
||||
if (idx < 0 || idx >= m_list_valid) return NULL;
|
||||
if (mode) *mode = m_list.Get()[idx].mode;
|
||||
if (score) *score=m_list.Get()[idx].score;
|
||||
return m_list.Get()[idx].val;
|
||||
}
|
||||
|
||||
void clear() { m_list_valid = 0; }
|
||||
void add(const char *p, int score=0x7FFFFFFF, int mode=MODE_FUNC)
|
||||
{
|
||||
rec *list = m_list.Get();
|
||||
int insert_after;
|
||||
for (insert_after = m_list_valid-1; insert_after >= 0 && score > list[insert_after].score; insert_after--);
|
||||
|
||||
const int maxsz = m_list.GetSize();
|
||||
WDL_ASSERT(m_list_valid <= maxsz);
|
||||
#ifdef _DEBUG
|
||||
{ for (int y = 0; y < m_list_valid; y ++) { WDL_ASSERT(list[y].val != NULL); } }
|
||||
#endif
|
||||
|
||||
if (insert_after+1 >= maxsz) return;
|
||||
|
||||
for (int y=insert_after; y>=0 && list[y].score == score; y--)
|
||||
{
|
||||
int d = strcmp(p,list[y].val);
|
||||
if (!d) return;
|
||||
if (d < 0) insert_after = y;
|
||||
}
|
||||
|
||||
if (m_list_valid < maxsz) m_list_valid++;
|
||||
rec r = list[maxsz-1];
|
||||
WDL_ASSERT(r.val || (!r.allocsz && !r.score));
|
||||
|
||||
r.mode = mode;
|
||||
r.score = score;
|
||||
const size_t plen = strlen(p);
|
||||
if (!r.val || (plen+1) > r.allocsz)
|
||||
{
|
||||
free(r.val);
|
||||
r.val = (char *)malloc( r.allocsz = wdl_max(plen,80)+36 );
|
||||
}
|
||||
if (WDL_NORMALLY(r.val)) strcpy(r.val,p);
|
||||
|
||||
m_list.Delete(maxsz-1);
|
||||
m_list.Insert(r,insert_after+1);
|
||||
WDL_ASSERT(maxsz == m_list.GetSize());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
extern int g_eel_editor_max_vis_suggestions;
|
||||
extern int g_eel_editor_flags; // &1=doubleclick function name defaults to jump
|
||||
|
||||
// add EEL syntax highlighting and paren matching, hooks for watch/etc
|
||||
class EEL_Editor : public WDL_CursesEditor
|
||||
{
|
||||
public:
|
||||
EEL_Editor(void *cursesCtx);
|
||||
virtual ~EEL_Editor();
|
||||
|
||||
virtual void draw_line_highlight(int y, const char *p, int *c_comment_state, int line_n);
|
||||
virtual int do_draw_line(const char *p, int *c_comment_state, int last_attr);
|
||||
virtual int GetCommentStateForLineStart(int line);
|
||||
virtual bool LineCanAffectOtherLines(const char *txt, int spos, int slen); // if multiline comment etc
|
||||
virtual void doWatchInfo(int c);
|
||||
virtual void doParenMatching();
|
||||
|
||||
virtual int onChar(int c);
|
||||
virtual void onRightClick(HWND hwnd);
|
||||
virtual void draw_bottom_line();
|
||||
|
||||
#ifdef WDL_IS_FAKE_CURSES
|
||||
virtual LRESULT onMouseMessage(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
#endif
|
||||
|
||||
virtual int overrideSyntaxDrawingForLine(int *skipcnt, const char **p, int *c_comment_state, int *last_attr) { return 0; }
|
||||
virtual int namedTokenHighlight(const char *tokStart, int len, int state);
|
||||
|
||||
virtual int is_code_start_line(const char *p) { return 0; } // pass NULL to see if code-start-lines are even used
|
||||
|
||||
virtual void draw_string_internal(int *skipcnt, const char *str, int amt, int *attr, int newAttr);
|
||||
virtual void draw_string_urlchk(int *skipcnt, const char *str, int amt, int *attr, int newAttr);
|
||||
virtual void draw_string(int *skipcnt, const char *str, int amt, int *attr, int newAttr, int comment_string_state=0);
|
||||
|
||||
virtual bool sh_draw_parenttokenstack_pop(char c);
|
||||
virtual bool sh_draw_parentokenstack_update(const char *tok, int toklen);
|
||||
virtual const char *sh_tokenize(const char **ptr, const char *endptr, int *lenOut, int *state);
|
||||
|
||||
virtual bool peek_want_VM_funcs() { return false; } // implement if syntax highlighting should (and can safely) call peek_get_VM()
|
||||
virtual void *peek_get_VM() { return NULL; } // returns NSEEL_VMCTX (if supported)
|
||||
virtual int peek_get_named_string_value(const char *name, char *sstr, size_t sstr_sz) { return -1; } // returns >=0 (index) if found
|
||||
virtual bool peek_get_numbered_string_value(double idx, char *sstr, size_t sstr_sz) { return false; }
|
||||
|
||||
virtual void peek_lock() { }
|
||||
virtual void peek_unlock() { }
|
||||
virtual void on_help(const char *str, int curChar) { } // curChar is current character if str is NULL
|
||||
|
||||
virtual bool line_has_openable_file(const char *line, int cursor_bytepos, char *fnout, size_t fnout_sz) { return false; }
|
||||
|
||||
enum {
|
||||
KEYWORD_MASK_BUILTIN_FUNC=1,
|
||||
KEYWORD_MASK_USER_FUNC=4,
|
||||
KEYWORD_MASK_USER_VAR=8
|
||||
};
|
||||
|
||||
// chkmask: KEYWORD_MASK_* or ~0 for all
|
||||
// ignoreline= line to ignore function defs on.
|
||||
virtual int peek_get_token_info(const char *name, char *sstr, size_t sstr_sz, int chkmask, int ignoreline);
|
||||
virtual void get_suggested_token_names(const char *fname, int chkmask, suggested_matchlist *list);
|
||||
virtual int fuzzy_match(const char *codestr, const char *refstr); // returns score
|
||||
|
||||
virtual void draw_top_line();
|
||||
|
||||
virtual void open_import_line();
|
||||
|
||||
virtual void get_extra_filepos_names(WDL_LogicalSortStringKeyedArray<int> * list, int pass) { }
|
||||
|
||||
// static helpers
|
||||
static WDL_TypedBuf<char> s_draw_parentokenstack;
|
||||
static int parse_format_specifier(const char *fmt_in, int *var_offs, int *var_len);
|
||||
|
||||
WDL_FastString m_suggestion;
|
||||
int m_suggestion_x,m_suggestion_y;
|
||||
HWND m_suggestion_hwnd;
|
||||
suggested_matchlist m_suggestion_list;
|
||||
int m_suggestion_hwnd_sel, m_suggestion_hwnd_scroll;
|
||||
POINT m_suggestion_hwnd_initmousepos;
|
||||
int m_suggestion_tokpos, m_suggestion_toklen; // bytepos/len
|
||||
int m_suggestion_curline_comment_state;
|
||||
|
||||
void ensure_code_func_cache_valid();
|
||||
|
||||
// list of code functions, first 4 bytes of the pointer is integer line offset
|
||||
// followed by name
|
||||
// followed by (parameter block)
|
||||
// followed by trailing info
|
||||
WDL_PtrList<char> m_code_func_cache;
|
||||
DWORD m_code_func_cache_time; // last GetTickCount() for invalidation
|
||||
int m_code_func_cache_lines; // last m_text.GetSize() for invalidation
|
||||
|
||||
|
||||
bool m_case_sensitive; // for function detection, and maybe other places
|
||||
const char *m_function_prefix; // defaults to "function "
|
||||
const char *m_comment_str; // defaults to "//"
|
||||
};
|
||||
|
||||
#endif
|
||||
80
oversampling/WDL/win32_curses/test.cpp
Normal file
80
oversampling/WDL/win32_curses/test.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "curses.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
win32CursesCtx g_curses_context; // we only need the one instance
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
|
||||
g_curses_context.want_getch_runmsgpump = 1; // non-block
|
||||
|
||||
curses_registerChildClass(hInstance);
|
||||
curses_CreateWindow(hInstance,&g_curses_context,"Sample Test App");
|
||||
#else
|
||||
int main() {
|
||||
#endif
|
||||
|
||||
|
||||
initscr();
|
||||
cbreak();
|
||||
noecho();
|
||||
nonl();
|
||||
intrflush(stdscr,FALSE);
|
||||
keypad(stdscr,TRUE);
|
||||
nodelay(stdscr,TRUE);
|
||||
raw();
|
||||
#if !defined(_WIN32) && !defined(MAC_NATIVE)
|
||||
ESCDELAY=0; // dont wait--at least on the console this seems to work.
|
||||
#endif
|
||||
|
||||
if (has_colors()) // we don't use color yet, but we could
|
||||
{
|
||||
start_color();
|
||||
init_pair(1, COLOR_WHITE, COLOR_BLUE); // normal status lines
|
||||
init_pair(2, COLOR_BLACK, COLOR_CYAN); // value
|
||||
}
|
||||
|
||||
erase();
|
||||
refresh();
|
||||
|
||||
float xpos=0,ypos=0, xdir=0.7, ydir=1.5;
|
||||
for (;;)
|
||||
{
|
||||
int t=getch();
|
||||
if (t==27) break;
|
||||
else if (t== KEY_LEFT) xdir *=0.9;
|
||||
else if (t== KEY_RIGHT) xdir *=1.1;
|
||||
else if (t== KEY_UP) ydir *=1.1;
|
||||
else if (t== KEY_DOWN) ydir *=0.9;
|
||||
|
||||
xpos+=xdir; ypos+=ydir;
|
||||
if (xpos >= COLS-1||xpos<1) { if (xpos<1)xpos=1; else xpos=COLS-1; xdir=-xdir; }
|
||||
if (ypos >= LINES-1||ypos<1) { if (ypos<1)ypos=1; else ypos=LINES-1; ydir=-ydir; }
|
||||
|
||||
erase();
|
||||
mvaddstr(ypos,xpos,"X");
|
||||
|
||||
|
||||
Sleep(10);
|
||||
#ifdef _WIN32
|
||||
if (!g_curses_context.m_hwnd) break;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
erase();
|
||||
refresh();
|
||||
endwin();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (g_curses_context.m_hwnd) DestroyWindow(g_curses_context.m_hwnd);
|
||||
curses_unregisterChildClass(hInstance);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user