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
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
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
Ord)

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

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

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

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

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

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

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

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

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

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

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