module Editfield(EditField, moveField, replaceField, setFieldDir, getField,getField',
                 deselectField, getSelection, getLastLineNo, getAft, getBef, getLnoEdge,
                 createField, dirint, splitnl, nlines) where
import HbcUtils(breakAt)
import Edtypes

--export EditField,newline,nlines,splitnl,
data EditField = F EDirection String String String Int Int 
                 deriving (EditField -> EditField -> Bool
(EditField -> EditField -> Bool)
-> (EditField -> EditField -> Bool) -> Eq EditField
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: EditField -> EditField -> Bool
$c/= :: EditField -> EditField -> Bool
== :: EditField -> EditField -> Bool
$c== :: EditField -> EditField -> Bool
Eq, Eq EditField
Eq EditField
-> (EditField -> EditField -> Ordering)
-> (EditField -> EditField -> Bool)
-> (EditField -> EditField -> Bool)
-> (EditField -> EditField -> Bool)
-> (EditField -> EditField -> Bool)
-> (EditField -> EditField -> EditField)
-> (EditField -> EditField -> EditField)
-> Ord EditField
EditField -> EditField -> Bool
EditField -> EditField -> Ordering
EditField -> EditField -> EditField
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: EditField -> EditField -> EditField
$cmin :: EditField -> EditField -> EditField
max :: EditField -> EditField -> EditField
$cmax :: EditField -> EditField -> EditField
>= :: EditField -> EditField -> Bool
$c>= :: EditField -> EditField -> Bool
> :: EditField -> EditField -> Bool
$c> :: EditField -> EditField -> Bool
<= :: EditField -> EditField -> Bool
$c<= :: EditField -> EditField -> Bool
< :: EditField -> EditField -> Bool
$c< :: EditField -> EditField -> Bool
compare :: EditField -> EditField -> Ordering
$ccompare :: EditField -> EditField -> Ordering
$cp1Ord :: Eq EditField
Ord)

--               bef     sel   aft     ^  lastlineno
--                            lno for selection edge

nlines :: [Char] -> Int
nlines [Char]
s = [Char] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((Char -> Bool) -> [Char] -> [Char]
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
newline) [Char]
s)

splitnl :: [Char] -> ([Char], [Char])
splitnl = Char -> [Char] -> ([Char], [Char])
forall a. Eq a => a -> [a] -> ([a], [a])
breakAt Char
newline

dirint :: EDirection -> p
dirint EDirection
ERight = p
1
dirint EDirection
ELeft = -p
1

befaft :: EDirection -> [a] -> [a] -> [a] -> ([a], [a])
befaft EDirection
dir [a]
bef [a]
sel [a]
aft =
    if EDirection
dir EDirection -> EDirection -> Bool
forall a. Eq a => a -> a -> Bool
== EDirection
ELeft then ([a]
bef, [a]
sel [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
aft) else ([a]
sel [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
bef, [a]
aft)

createField :: [Char] -> EditField
createField [Char]
s = EDirection -> [Char] -> [Char] -> [Char] -> Int -> Int -> EditField
F EDirection
ERight [] [] [Char]
s Int
0 ([Char] -> Int
nlines [Char]
s)
getLnoEdge :: EditField -> (Int, ([Char], [Char]))
getLnoEdge (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) =
    (Int
elno, EDirection -> [Char] -> [Char] -> [Char] -> ([Char], [Char])
forall a. EDirection -> [a] -> [a] -> [a] -> ([a], [a])
befaft EDirection
dir [Char]
bef [Char]
sel [Char]
aft)
getBef :: EditField -> [Char]
getBef (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) = [Char]
bef
getAft :: EditField -> [Char]
getAft (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) = [Char]
aft
getLastLineNo :: EditField -> Int
getLastLineNo (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) = Int
lno
getSelection :: EditField -> [Char]
getSelection (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) =
    if EDirection
dir EDirection -> EDirection -> Bool
forall a. Eq a => a -> a -> Bool
== EDirection
ELeft then [Char]
sel else [Char] -> [Char]
forall a. [a] -> [a]
reverse [Char]
sel

deselectField :: EditField -> EditField
deselectField (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) =
    let ([Char]
bef', [Char]
aft') = EDirection -> [Char] -> [Char] -> [Char] -> ([Char], [Char])
forall a. EDirection -> [a] -> [a] -> [a] -> ([a], [a])
befaft EDirection
dir [Char]
bef [Char]
sel [Char]
aft
    in  EDirection -> [Char] -> [Char] -> [Char] -> Int -> Int -> EditField
F EDirection
dir [Char]
bef' [] [Char]
aft' Int
elno Int
lno

getField :: EditField -> [Char]
getField EditField
f = [Char] -> [Char]
forall a. [a] -> [a]
reverse (EditField -> [Char]
getBef EditField
f) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ EditField -> [Char]
getSelection EditField
f [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ EditField -> [Char]
getAft EditField
f
getField' :: EditField -> ([Char], [Char], [Char])
getField' EditField
f = ([Char] -> [Char]
forall a. [a] -> [a]
reverse (EditField -> [Char]
getBef EditField
f),EditField -> [Char]
getSelection EditField
f,EditField -> [Char]
getAft EditField
f)

setFieldDir :: EDirection -> EditField -> EditField
setFieldDir EDirection
ndir field :: EditField
field@(F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) =
    if EDirection
ndir EDirection -> EDirection -> Bool
forall a. Eq a => a -> a -> Bool
== EDirection
dir then
        EditField
field
    else
        let elno' :: Int
elno' = Int
elno Int -> Int -> Int
forall a. Num a => a -> a -> a
+ EDirection -> Int
forall p. Num p => EDirection -> p
dirint EDirection
ndir Int -> Int -> Int
forall a. Num a => a -> a -> a
* [Char] -> Int
nlines [Char]
sel
        in  EDirection -> [Char] -> [Char] -> [Char] -> Int -> Int -> EditField
F EDirection
ndir [Char]
bef ([Char] -> [Char]
forall a. [a] -> [a]
reverse [Char]
sel) [Char]
aft Int
elno' Int
lno

replaceField :: EditField -> [Char] -> EditField
replaceField (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) [Char]
s =
    let linessel :: Int
linessel = [Char] -> Int
nlines [Char]
sel
        liness :: Int
liness = [Char] -> Int
nlines [Char]
s
        elno' :: Int
elno' = Int
elno Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
liness Int -> Int -> Int
forall a. Num a => a -> a -> a
- (if EDirection
dir EDirection -> EDirection -> Bool
forall a. Eq a => a -> a -> Bool
== EDirection
ERight then Int
linessel else Int
0)
        lno' :: Int
lno' = Int
lno Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
liness Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
linessel)
    in  EDirection -> [Char] -> [Char] -> [Char] -> Int -> Int -> EditField
F EDirection
ERight ([Char] -> [Char]
forall a. [a] -> [a]
reverse [Char]
s [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
bef) [] [Char]
aft Int
elno' Int
lno'

moveField :: IsSelect -> EditField -> EditStopFn -> (EditField,String)
moveField :: Bool -> EditField -> EditStopFn -> (EditField, [Char])
moveField Bool
issel (F EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno Int
lno) EditStopFn
sf =
    let mo :: EDirection
-> [Char]
-> [Char]
-> [Char]
-> Int
-> [Char]
-> EditStopFn
-> (EditField, [Char])
mo EDirection
dir' [Char]
bef' [Char]
sel' [Char]
aft' Int
elno' [Char]
acc EditStopFn
sf =
            let stop :: (EditField, [Char])
stop = (EDirection -> [Char] -> [Char] -> [Char] -> Int -> Int -> EditField
F EDirection
dir' [Char]
bef' [Char]
sel' [Char]
aft' Int
elno' Int
lno, [Char]
acc)
                ([Char]
b, [Char]
a) = EDirection -> [Char] -> [Char] -> [Char] -> ([Char], [Char])
forall a. EDirection -> [a] -> [a] -> [a] -> ([a], [a])
befaft EDirection
dir' [Char]
bef' [Char]
sel' [Char]
aft'
            in case EditStopFn
sf [Char]
b [Char]
a of 
		 EditStopChoice
EdStop -> (EditField, [Char])
stop
		 EdGo EDirection
wdir EditStopFn
sf' -> 
		    let next :: Char
-> EDirection -> [Char] -> [Char] -> [Char] -> (EditField, [Char])
next Char
c EDirection
dir'' [Char]
bef'' [Char]
sel'' [Char]
aft'' =
			    let elno'' :: Int
elno'' =
				    if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
newline then
					EDirection -> Int
forall p. Num p => EDirection -> p
dirint EDirection
wdir Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
elno'
				    else
					Int
elno'
			    in  EDirection
-> [Char]
-> [Char]
-> [Char]
-> Int
-> [Char]
-> EditStopFn
-> (EditField, [Char])
mo EDirection
dir'' [Char]
bef'' [Char]
sel'' [Char]
aft'' Int
elno'' (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
acc) EditStopFn
sf'
		    in  if EDirection
wdir EDirection -> EDirection -> Bool
forall a. Eq a => a -> a -> Bool
== EDirection
dir' Bool -> Bool -> Bool
|| [Char] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Char]
sel' then
			    case EDirection
wdir of
			      EDirection
ELeft -> case [Char]
bef' of
					 [] -> (EditField, [Char])
stop
					 Char
c:[Char]
bef'' -> Char
-> EDirection -> [Char] -> [Char] -> [Char] -> (EditField, [Char])
next Char
c EDirection
wdir [Char]
bef'' (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
sel') [Char]
aft'
			      EDirection
ERight -> case [Char]
aft' of
					  [] -> (EditField, [Char])
stop
					  Char
c:[Char]
aft'' -> Char
-> EDirection -> [Char] -> [Char] -> [Char] -> (EditField, [Char])
next Char
c EDirection
wdir [Char]
bef' (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
sel') [Char]
aft''
			else
			    let Char
c:[Char]
sel'' = [Char]
sel'
			    in  case EDirection
dir' of
				  EDirection
ELeft -> Char
-> EDirection -> [Char] -> [Char] -> [Char] -> (EditField, [Char])
next Char
c EDirection
dir' (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
bef') [Char]
sel'' [Char]
aft'
				  EDirection
ERight -> Char
-> EDirection -> [Char] -> [Char] -> [Char] -> (EditField, [Char])
next Char
c EDirection
dir' [Char]
bef' [Char]
sel'' (Char
cChar -> [Char] -> [Char]
forall a. a -> [a] -> [a]
:[Char]
aft')
        (EditField
field, [Char]
acc) = EDirection
-> [Char]
-> [Char]
-> [Char]
-> Int
-> [Char]
-> EditStopFn
-> (EditField, [Char])
mo EDirection
dir [Char]
bef [Char]
sel [Char]
aft Int
elno [] EditStopFn
sf
    in  if Bool
issel then (EditField
field, [Char]
acc) else (EditField -> EditField
deselectField EditField
field, [])