mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 02:11:19 +00:00
[qwaq] Fix page up/down and deal with tabs
This commit is contained in:
parent
927a446bd3
commit
055ea46337
7 changed files with 216 additions and 30 deletions
|
@ -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 \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
23
ruamoko/qwaq/editor/status.h
Normal file
23
ruamoko/qwaq/editor/status.h
Normal 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
|
43
ruamoko/qwaq/editor/status.r
Normal file
43
ruamoko/qwaq/editor/status.r
Normal 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
|
Loading…
Reference in a new issue