#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <cursor.h>
#include <mouse.h>
#include <keyboard.h>
#include <frame.h>
#include <fcall.h>
#include <plumb.h>
#include "dat.h"
#include "fns.h"

enum
{
	None = 0,
	Fore = '+',
	Back = '-',
};

enum
{
	Char,
	Line,
};

int
isaddrc(int r)
{
	if(r && utfrune("0123456789+-/$.#,;", r)!=nil)
		return TRUE;
	return FALSE;
}

/*
 * quite hard: could be almost anything but white space, but we are a little conservative,
 * aiming for regular expressions of alphanumerics and no white space
 */
int
isregexc(int r)
{
	if(r == 0)
		return FALSE;
	if(isalnum(r))
		return TRUE;
	if(utfrune("^+-.*?#,;[]()$", r)!=nil)
		return TRUE;
	return FALSE;
}

Range
number(Mntdir *md, Text *t, Range r, int line, int dir, int size, int *evalp)
{
	uint q0, q1;

	if(size == Char){
		if(dir == Fore)
			line = r.q1+line;
		else if(dir == Back){
			if(r.q0==0 && line>0)
				r.q0 = t->file->b.nc;
			line = r.q0 - line;
		}
		if(line<0 || line>t->file->b.nc)
			goto Rescue;
		*evalp = TRUE;
		return (Range){line, line};
	}
	q0 = r.q0;
	q1 = r.q1;
	switch(dir){
	case None:
		q0 = 0;
		q1 = 0;
	Forward:
		while(line>0 && q1<t->file->b.nc)
			if(textreadc(t, q1++) == '\n' || q1==t->file->b.nc)
				if(--line > 0)
					q0 = q1;
		if(line > 0)
			goto Rescue;
		break;
	case Fore:
		if(q1 > 0)
			while(textreadc(t, q1-1) != '\n')
				q1++;
		q0 = q1;
		goto Forward;
	case Back:
		if(q0 < t->file->b.nc)
			while(q0>0 && textreadc(t, q0-1)!='\n')
				q0--;
		q1 = q0;
		while(line>0 && q0>0){
			if(textreadc(t, q0-1) == '\n'){
				if(--line >= 0)
					q1 = q0;
			}
			--q0;
		}
		if(line > 0)
			goto Rescue;
		while(q0>0 && textreadc(t, q0-1)!='\n')
			--q0;
	}
	*evalp = TRUE;
	return (Range){q0, q1};

    Rescue:
	if(md != nil)
		warning(nil, "address out of range\n");
	*evalp = FALSE;
	return r;
}


Range
regexp(Mntdir *md, Text *t, Range lim, Range r, Rune *pat, int dir, int *foundp)
{
	int found;
	Rangeset sel;
	int q;

	if(pat[0] == '\0' && rxnull()){
		warning(md, "no previous regular expression\n");
		*foundp = FALSE;
		return r;
	}
	if(pat[0] && rxcompile(pat) == FALSE){
		*foundp = FALSE;
		return r;
	}
	if(dir == Back)
		found = rxbexecute(t, r.q0, &sel);
	else{
		if(lim.q0 < 0)
			q = Infinity;
		else
			q = lim.q1;
		found = rxexecute(t, nil, r.q1, q, &sel);
	}
	if(!found && md==nil)
		warning(nil, "no match for regexp\n");
	*foundp = found;
	return sel.r[0];
}

Range
address(Mntdir *md, Text *t, Range lim, Range ar, void *a, uint q0, uint q1, int (*getc)(void*, uint),  int *evalp, uint *qp)
{
	int dir, size, npat;
	int prevc, c, nc, n;
	uint q;
	Rune *pat;
	Range r, nr;

	r = ar;
	q = q0;
	dir = None;
	size = Line;
	c = 0;
	while(q < q1){
		prevc = c;
		c = (*getc)(a, q++);
		switch(c){
		default:
			*qp = q-1;
			return r;
		case ';':
			ar = r;
			/* fall through */
		case ',':
			if(prevc == 0)	/* lhs defaults to 0 */
				r.q0 = 0;
			if(q>=q1 && t!=nil && t->file!=nil)	/* rhs defaults to $ */
				r.q1 = t->file->b.nc;
			else{
				nr = address(md, t, lim, ar, a, q, q1, getc, evalp, &q);
				r.q1 = nr.q1;
			}
			*qp = q;
			return r;
		case '+':
		case '-':
			if(*evalp && (prevc=='+' || prevc=='-'))
				if((nc=(*getc)(a, q))!='#' && nc!='/' && nc!='?')
					r = number(md, t, r, 1, prevc, Line, evalp);	/* do previous one */
			dir = c;
			break;
		case '.':
		case '$':
			if(q != q0+1){
				*qp = q-1;
				return r;
			}
			if(*evalp)
				if(c == '.')
					r = ar;
				else
					r = (Range){t->file->b.nc, t->file->b.nc};
			if(q < q1)
				dir = Fore;
			else
				dir = None;
			break;
		case '#':
			if(q==q1 || (c=(*getc)(a, q++))<'0' || '9'<c){
				*qp = q-1;
				return r;
			}
			size = Char;
			/* fall through */
		case '0': case '1': case '2': case '3': case '4':
		case '5': case '6': case '7': case '8': case '9':
			n = c -'0';
			while(q<q1){
				c = (*getc)(a, q++);
				if(c<'0' || '9'<c){
					q--;
					break;
				}
				n = n*10+(c-'0');
			}
			if(*evalp)
				r = number(md, t, r, n, dir, size, evalp);
			dir = None;
			size = Line;
			break;
		case '?':
			dir = Back;
			/* fall through */
		case '/':
			npat = 0;
			pat = nil;
			while(q<q1){
				c = (*getc)(a, q++);
				switch(c){
				case '\n':
					--q;
					goto out;
				case '\\':
					pat = runerealloc(pat, npat+1);
					pat[npat++] = c;
					if(q == q1)
						goto out;
					c = (*getc)(a, q++);
					break;
				case '/':
					goto out;
				}
				pat = runerealloc(pat, npat+1);
				pat[npat++] = c;
			}
		    out:
			pat = runerealloc(pat, npat+1);
			pat[npat] = 0;
			if(*evalp)
				r = regexp(md, t, lim, r, pat, dir, evalp);
			free(pat);
			dir = None;
			size = Line;
			break;
		}
	}
	if(*evalp && dir != None)
		r = number(md, t, r, 1, dir, Line, evalp);	/* do previous one */
	*qp = q;
	return r;
}
