mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-21 03:01:15 +00:00
[qwaq] Implement word left and right
The word boundaries are currently vary simple, just transitions from alnum_ (as it was in my old editor and in Borland's editors), but the basic logic is working.
This commit is contained in:
parent
75ce07a14c
commit
3cd0d68774
6 changed files with 126 additions and 22 deletions
|
@ -162,7 +162,10 @@ prevWord (txtbuffer_t *buffer, unsigned ptr)
|
|||
if (ptr > 0) {
|
||||
while (ptr > 0) {
|
||||
char c = getChar (buffer, ptr - 1);
|
||||
if (!isword (c)) {
|
||||
if (c == '\n') {
|
||||
return ptr;
|
||||
}
|
||||
if (isword (c)) {
|
||||
break;
|
||||
}
|
||||
ptr--;
|
||||
|
@ -172,7 +175,7 @@ prevWord (txtbuffer_t *buffer, unsigned ptr)
|
|||
if (c == '\n') {
|
||||
return ptr;
|
||||
}
|
||||
if (isword (c)) {
|
||||
if (!isword (c)) {
|
||||
break;
|
||||
}
|
||||
ptr--;
|
||||
|
@ -619,6 +622,17 @@ bi_i_EditBuffer__prevNonSpace_ (progs_t *pr)
|
|||
R_INT (pr) = prevNonSpace (buffer->txtbuffer, ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
bi_i_EditBuffer__isWord_ (progs_t *pr)
|
||||
{
|
||||
qwaq_ebresources_t *res = PR_Resources_Find (pr, "qwaq-editbuffer");
|
||||
int buffer_id = P_STRUCT (pr, qwaq_editbuffer_t, 0).buffer;
|
||||
editbuffer_t *buffer = get_editbuffer (res, __FUNCTION__, buffer_id);
|
||||
unsigned ptr = P_UINT (pr, 2);
|
||||
|
||||
R_INT (pr) = isword (getChar (buffer->txtbuffer, ptr));
|
||||
}
|
||||
|
||||
static void
|
||||
bi_i_EditBuffer__nextWord_ (progs_t *pr)
|
||||
{
|
||||
|
@ -968,6 +982,7 @@ static builtin_t builtins[] = {
|
|||
{"_i_EditBuffer__prevChar_", bi_i_EditBuffer__prevChar_, -1},
|
||||
{"_i_EditBuffer__nextNonSpace_", bi_i_EditBuffer__nextNonSpace_, -1},
|
||||
{"_i_EditBuffer__prevNonSpace_", bi_i_EditBuffer__prevNonSpace_, -1},
|
||||
{"_i_EditBuffer__isWord_", bi_i_EditBuffer__isWord_, -1},
|
||||
{"_i_EditBuffer__nextWord_", bi_i_EditBuffer__nextWord_, -1},
|
||||
{"_i_EditBuffer__prevWord_", bi_i_EditBuffer__prevWord_, -1},
|
||||
{"_i_EditBuffer__nextLine_", bi_i_EditBuffer__nextLine_, -1},
|
||||
|
|
|
@ -34,6 +34,7 @@ typedef struct eb_color_s {
|
|||
- (unsigned) prevChar: (unsigned) charPtr;
|
||||
- (unsigned) nextNonSpace: (unsigned) charPtr;
|
||||
- (unsigned) prevNonSpace: (unsigned) charPtr;
|
||||
- (int) isWord: (unsigned) charPtr;
|
||||
- (unsigned) nextWord: (unsigned) wordPtr;
|
||||
- (unsigned) prevWord: (unsigned) wordPtr;
|
||||
- (unsigned) nextLine: (unsigned) linePtr;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
- (unsigned) prevChar: (unsigned) charPtr = #0;
|
||||
- (unsigned) nextNonSpace: (unsigned) charPtr = #0;
|
||||
- (unsigned) prevNonSpace: (unsigned) charPtr = #0;
|
||||
- (int) isWord: (unsigned) charPtr = #0;
|
||||
- (unsigned) nextWord: (unsigned) wordPtr = #0;
|
||||
- (unsigned) prevWord: (unsigned) wordPtr = #0;
|
||||
- (unsigned) nextLine: (unsigned) linePtr = #0;
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
-charDown;
|
||||
-charLeft;
|
||||
-charRight;
|
||||
-wordLeft;
|
||||
-wordRight;
|
||||
-moveBOL;
|
||||
-moveEOL;
|
||||
|
||||
|
|
|
@ -7,6 +7,23 @@
|
|||
|
||||
@implementation Editor
|
||||
|
||||
static int
|
||||
center (unsigned v, int len)
|
||||
{
|
||||
return v > len / 2 ? v / 2 : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
trackCursor (Editor *self)
|
||||
{
|
||||
unsigned cx = [self.buffer charPos:self.line_index at:self.char_index];
|
||||
if (self.cursor.x != cx) {
|
||||
if (self.char_index < [self.buffer getEOT]) {
|
||||
int c = [self.buffer getChar:self.char_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-initWithRect:(Rect) rect file:(string) filename path:(string) filepath
|
||||
{
|
||||
if (!(self = [super initWithRect: rect])) {
|
||||
|
@ -168,10 +185,18 @@ handleEvent (Editor *self, qwaq_event_t *event)
|
|||
[self charDown];
|
||||
return 1;
|
||||
case QFK_LEFT:
|
||||
[self charLeft];
|
||||
if (event.key.shift & qe_control) {
|
||||
[self wordLeft];
|
||||
} else {
|
||||
[self charLeft];
|
||||
}
|
||||
return 1;
|
||||
case QFK_RIGHT:
|
||||
[self charRight];
|
||||
if (event.key.shift & qe_control) {
|
||||
[self wordRight];
|
||||
} else {
|
||||
[self charRight];
|
||||
}
|
||||
return 1;
|
||||
case QFK_HOME:
|
||||
[self moveBOL];
|
||||
|
@ -376,6 +401,78 @@ handleEvent (Editor *self, qwaq_event_t *event)
|
|||
return self;
|
||||
}
|
||||
|
||||
-wordLeft
|
||||
{
|
||||
[self recenter:0];
|
||||
//unsigned oc = char_index;
|
||||
Point b = base;
|
||||
|
||||
do {
|
||||
if (char_index && char_index == line_index) {
|
||||
line_index = [buffer prevLine: line_index];
|
||||
char_index = [buffer getEOL: line_index];
|
||||
if (--cursor.y < b.y) {
|
||||
b.y = cursor.y;
|
||||
}
|
||||
}
|
||||
char_index = [buffer prevWord:char_index];
|
||||
} while (char_index && char_index < [buffer getEOT]
|
||||
&& ![buffer isWord:char_index]);
|
||||
|
||||
cursor.x = [buffer charPos:line_index at:char_index];
|
||||
if (cursor.x < b.x) {
|
||||
b.x = cursor.x;
|
||||
} else if (cursor.x >= b.x) {
|
||||
b.x = center (b.x, xlen);
|
||||
}
|
||||
base.x = b.x;
|
||||
[vScrollBar setIndex:b.y];
|
||||
trackCursor (self);
|
||||
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-wordRight
|
||||
{
|
||||
[self recenter:0];
|
||||
//unsigned oc = char_index;
|
||||
Point b = base;
|
||||
|
||||
if (char_index >= [buffer getEOT]) {
|
||||
return self;
|
||||
}
|
||||
if ([buffer getChar:char_index] == '\n') {
|
||||
while ([buffer getChar:char_index] == '\n') {
|
||||
char_index = line_index = [buffer nextLine:line_index];
|
||||
if (++cursor.y >= b.y + ylen) {
|
||||
b.y = cursor.y + 1 - ylen;
|
||||
}
|
||||
if (char_index >= [buffer getEOT]) {
|
||||
break;
|
||||
}
|
||||
if (![buffer isWord:char_index]) {
|
||||
char_index = [buffer nextWord: char_index];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
char_index = [buffer nextWord: char_index];
|
||||
}
|
||||
|
||||
cursor.x = [buffer charPos:line_index at:char_index];
|
||||
if (cursor.x < b.x) {
|
||||
b.x = cursor.x;
|
||||
} else if (cursor.x >= b.x) {
|
||||
b.x = center (b.x, xlen);
|
||||
}
|
||||
base.x = b.x;
|
||||
[vScrollBar setIndex:b.y];
|
||||
trackCursor (self);
|
||||
[self moveCursor: {cursor.x - base.x, cursor.y - base.y}];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
-moveBOL
|
||||
{
|
||||
char_index = line_index;
|
||||
|
@ -414,28 +511,11 @@ handleEvent (Editor *self, qwaq_event_t *event)
|
|||
-recenter:(int) force
|
||||
{
|
||||
if (force || cursor.y < base.y || cursor.y - base.y >= ylen) {
|
||||
unsigned target;
|
||||
if (cursor.y < ylen / 2) {
|
||||
target = 0;
|
||||
} else {
|
||||
target = cursor.y - ylen / 2;
|
||||
}
|
||||
[self scrollTo:target];
|
||||
[self scrollTo: center (cursor.y, ylen)];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
trackCursor (Editor *self)
|
||||
{
|
||||
unsigned cx = [self.buffer charPos:self.line_index at:self.char_index];
|
||||
if (self.cursor.x != cx) {
|
||||
if (self.char_index < [self.buffer getEOT]) {
|
||||
int c = [self.buffer getChar:self.char_index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-gotoLine:(unsigned) line
|
||||
{
|
||||
if (line > cursor.y) {
|
||||
|
|
|
@ -13,6 +13,11 @@ typedef enum {
|
|||
qe_keydown = 0x0020,
|
||||
} qwaq_key_event;
|
||||
|
||||
typedef enum {
|
||||
qe_shift = 1,
|
||||
qe_control = 4,
|
||||
} qwaq_key_shift;
|
||||
|
||||
typedef enum {
|
||||
qe_command = 0x0200, // application level command
|
||||
qe_broadcast = 0x0400,
|
||||
|
|
Loading…
Reference in a new issue