[qwaq] Fix page up/down and deal with tabs

This commit is contained in:
Bill Currie 2021-06-10 12:13:55 +09:00
parent 927a446bd3
commit 055ea46337
7 changed files with 216 additions and 30 deletions

View file

@ -27,6 +27,7 @@ qwaq_app_dat_src= \
ruamoko/qwaq/debugger/typeencodings.r \
ruamoko/qwaq/editor/editbuffer.r \
ruamoko/qwaq/editor/editor.r \
ruamoko/qwaq/editor/status.r \
ruamoko/qwaq/ui/button.r \
ruamoko/qwaq/ui/draw.r \
ruamoko/qwaq/ui/garray.r \
@ -124,6 +125,7 @@ EXTRA_DIST += \
ruamoko/qwaq/debugger/views/voidview.h \
ruamoko/qwaq/editor/editbuffer.h \
ruamoko/qwaq/editor/editor.h \
ruamoko/qwaq/editor/status.h \
ruamoko/qwaq/qwaq-app.h \
ruamoko/qwaq/qwaq.h \
ruamoko/qwaq/ui/button.h \

View file

@ -9,6 +9,7 @@
@class ProxyView;
@class Editor;
@class EditStatus;
@class ScrollBar;
@class Window;
@class Array;
@ -33,6 +34,7 @@
Window *source_window;
ScrollBar *source_scrollbar;
EditStatus *source_status;
ProxyView *file_proxy;
Array *files;
Editor *current_file;

View file

@ -40,6 +40,9 @@
source_scrollbar = [ScrollBar vertical:s.height - 2 at:{s.width - 1, 1}];
[source_window insert:source_scrollbar];
source_status = [EditStatus withRect:{{1, 0}, {2, 1}}];
[source_window insert:source_status];
return self;
}
@ -77,6 +80,7 @@
[[current_file gotoLine:state.line - 1] highlightLine];
[[current_file onEvent] addListener: self :@selector(proxy_event::)];
[current_file setVerticalScrollBar:source_scrollbar];
[current_file setStatusView:source_status];
//FIXME id<View>?
[source_window insertSelected: (View *) file_proxy];
[source_window setTitle:[current_file filename]];
@ -111,6 +115,7 @@
[file_proxy setView:file];
[[file onEvent] addListener:self :@selector(proxy_event::)];
[file setVerticalScrollBar:source_scrollbar];
[file setStatusView:source_status];
[source_window setTitle:[file filename]];
current_file = file;
}

View file

@ -2,15 +2,18 @@
#define __qwaq_editor_editor_h
#include "ruamoko/qwaq/editor/editbuffer.h"
#include "ruamoko/qwaq/editor/status.h"
#include "ruamoko/qwaq/ui/view.h"
@class Editor;
@class EditBuffer;
@class ListenerGroup;
@class EditStatus;
@interface Editor : View
{
EditBuffer *buffer;
EditStatus *status;
DrawBuffer *linebuffer;
eb_sel_t selection;
unsigned base_index; // top left corner
@ -22,20 +25,28 @@
unsigned line_count;
string filename;
string filepath;
int modified;
CursorMode cursorMode;
int virtualInsert;
int cursorThroughTabs;
}
+(Editor *)withRect:(Rect)rect file:(string)filename;
+(Editor *)withRect:(Rect)rect file:(string)filename path:(string)filepath;
-(string)filename;
-(string)filepath;
-(Point)cursor;
-setStatusView:(EditStatus *)status;
-scrollUp:(unsigned) count;
-scrollDown:(unsigned) count;
-scrollLeft:(unsigned) count;
-scrollRight:(unsigned) count;
-cursorUp:(unsigned) count;
-cursorDown:(unsigned) count;
-cursorLeft:(unsigned) count;
-cursorRight:(unsigned) count;
-pageUp;
-pageDown;
-charUp;
-charDown;
-charLeft;
-charRight;
-recenter:(int) force;
-gotoLine:(unsigned) line;

View file

@ -25,6 +25,7 @@
options = ofCanFocus | ofRelativeEvents;
[onViewScrolled addListener:self :@selector(onScroll:)];
[self setCursorVisible:1];
return self;
}
@ -69,6 +70,45 @@
return cursor;
}
-setStatusView:(EditStatus *)status
{
self.status = status;
[status setModified:modified];
[status setCursorMode:cursorMode];
[status redraw];
return self;
}
-trackCursor:(int)fwd
{
unsigned tx = [buffer charPos:line_index at:char_index];
cursorMode &= ~cmVInsert;
if (tx != cursor.x) {
if (char_index < [buffer getEOT]) {
int c = [buffer getChar:char_index];
if (virtualInsert) {
if (c != '\t' || cursorThroughTabs) {
cursorMode |= cmVInsert;
goto done;
}
}
if (c == '\t' && fwd) {
tx = [buffer charPos:line_index at:++char_index];
}
} else if (virtualInsert) {
cursorMode |= cmVInsert;
goto done;
}
cursor.x = tx;
}
done:
[status setCursorMode:cursorMode];
[status redraw];
return self;
}
-draw
{
[super draw];
@ -116,22 +156,22 @@ handleEvent (Editor *self, qwaq_event_t *event)
} else if (event.what == qe_keydown) {
switch (event.key.code) {
case QFK_PAGEUP:
[self scrollUp: self.ylen];
[self pageUp];
return 1;
case QFK_PAGEDOWN:
[self scrollDown: self.ylen];
[self pageDown];
return 1;
case QFK_UP:
[self cursorUp: 1];
[self charUp];
return 1;
case QFK_DOWN:
[self cursorDown: 1];
[self charDown];
return 1;
case QFK_LEFT:
[self cursorLeft: 1];
[self charLeft];
return 1;
case QFK_RIGHT:
[self cursorRight: 1];
[self charRight];
return 1;
}
}
@ -150,23 +190,35 @@ handleEvent (Editor *self, qwaq_event_t *event)
-scrollUp:(unsigned) count
{
unsigned index;
unsigned lines;
if (count == 1) {
base_index = [buffer prevLine: base_index];
index = [buffer prevLine: base_index];
} else {
base_index = [buffer prevLine: base_index :count];
index = [buffer prevLine: base_index :count];
}
lines = [buffer countLines: {index, base_index - index}];
base.y -= lines;
base_index = index;
[self redraw];
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
return self;
}
-scrollDown:(unsigned) count
{
unsigned index;
unsigned lines;
if (count == 1) {
base_index = [buffer nextLine: base_index];
index = [buffer nextLine: base_index];
} else {
base_index = [buffer nextLine: base_index :count];
index = [buffer nextLine: base_index :count];
}
lines = [buffer countLines: {base_index, index - base_index}];
base.y += lines;
base_index = index;
[self redraw];
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
return self;
}
@ -207,15 +259,57 @@ handleEvent (Editor *self, qwaq_event_t *event)
return self;
}
-cursorUp:(unsigned)count
-pageUp
{
[self recenter:0];
if (count > cursor.y) {
count = cursor.y;
unsigned count = cursor.y;
if (count > ylen) {
count = ylen;
}
cursor.y -= count;
line_index = [buffer prevLine:line_index :count];
if (count) {
cursor.y -= count;
[vScrollBar setIndex:[vScrollBar index] - count];
line_index = [buffer prevLine:line_index :count];
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:1];
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
}
return self;
}
-pageDown
{
[self recenter:0];
unsigned count = line_count - cursor.y;
if (count > ylen) {
count = ylen;
}
if (count) {
cursor.y += count;
[vScrollBar setIndex:[vScrollBar index] + count];
line_index = [buffer nextLine:line_index :count];
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:1];
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
}
return self;
}
-charUp
{
[self recenter:0];
if (cursor.y < 1) {
return self;
}
cursor.y--;
line_index = [buffer prevLine:line_index :1];
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:1];
if (base.y > cursor.y) {
[vScrollBar setIndex:cursor.y];
}
@ -223,15 +317,17 @@ handleEvent (Editor *self, qwaq_event_t *event)
return self;
}
-cursorDown:(unsigned)count
-charDown
{
[self recenter:0];
if (count > line_count - cursor.y) {
count = line_count - cursor.y;
if (cursor.y >= line_count) {
return self;
}
cursor.y += count;
line_index = [buffer nextLine:line_index :count];
cursor.y++;
line_index = [buffer nextLine:line_index :1];
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:1];
if (base.y + ylen - 1 < cursor.y) {
[vScrollBar setIndex:cursor.y + 1 - ylen];
}
@ -239,14 +335,16 @@ handleEvent (Editor *self, qwaq_event_t *event)
return self;
}
-cursorLeft:(unsigned)count
-charLeft
{
[self recenter:0];
if (count > cursor.x) {
count = cursor.x;
if (cursor.x < 1) {
return self;
}
cursor.x -= count;
cursor.x--;
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:0];
if (base.x > cursor.x) {
[hScrollBar setIndex:cursor.x];
}
@ -254,12 +352,14 @@ handleEvent (Editor *self, qwaq_event_t *event)
return self;
}
-cursorRight:(unsigned)count
-charRight
{
[self recenter:0];
// FIXME handle horizontal scrolling and how to deal with max scroll
cursor.x += count;
cursor.x++;
char_index = [buffer charPtr:line_index at:cursor.x];
[self trackCursor:1];
if (base.x + xlen - 1 < cursor.x) {
[hScrollBar setIndex:cursor.x + 1 - xlen];
}

View file

@ -0,0 +1,23 @@
#ifndef __qwaq_editor_status_h
#define __qwaq_editor_status_h
#include "ruamoko/qwaq/ui/view.h"
typedef enum {
cmInsert,
cmTypeOver,
cmVInsert,
cmVTypeOver,
} CursorMode;
@interface EditStatus : View
{
CursorMode cursorMode;
int modified;
}
+(EditStatus *)withRect:(Rect)rect;
-setCursorMode:(CursorMode)mode;
-setModified:(int)modified;
@end
#endif//__qwaq_editor_status_h

View file

@ -0,0 +1,43 @@
#include "ruamoko/qwaq/editor/status.h"
static int cursor_modes[] = { 'I', 'O', 'i', 'o' };
@implementation EditStatus
-initWithRect:(Rect)rect
{
if (!(self = [super initWithRect: rect])) {
return nil;
}
growMode = gfGrowNone;
return self;
}
+(EditStatus *)withRect:(Rect)rect
{
return [[self alloc] initWithRect:rect];
}
-setCursorMode:(CursorMode)mode
{
cursorMode = mode;
return self;
}
-setModified:(int)modified
{
self.modified = modified;
return self;
}
-draw
{
[super draw];
if (modified) {
[self mvaddch:{0, 0}, '*'];
}
[self mvaddch:{1, 0}, cursor_modes[cursorMode]];
return self;
}
@end