EdSelection.icl 2.29 KB
Newer Older
Diederik van Arkel's avatar
Diederik van Arkel committed
1 2
implementation module EdSelection

3 4
// non-visual operations on selections

Diederik van Arkel's avatar
Diederik van Arkel committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
import StdList, StdFunc, StdBool, StdArray, StdTuple
import EdPosition, EdText

:: Selection 
	= { start	:: Position
	  , end		:: Position
	  }
	  
// An empty selection has the same start as end position.

emptySelection :: Selection
emptySelection 
  = { start	= { col = 0, row = 0 }
    , end	= { col = 0, row = 0 }
    }

lineSelection :: !Int -> Selection
lineSelection lnr =
	{ start	= {row = dec lnr,	col = 0}
	, end	= {row = lnr,		col = 0}
	}

isEmptySelection :: !Selection -> Bool
isEmptySelection { start, end }
  = start == end

notEmptySelection :: !Selection -> Bool
notEmptySelection { start, end }
  = start <> end

// After ordering a selection the start position is smaller
// the end position.

orderSelection :: !Selection -> Selection
orderSelection { start, end }
  | start < end
	= { start = start, end = end   }
    = { start = end,   end = start }

// The function changeSelection computes which selections 
// have to hilited if the selection change from the old to the
// new one.

changeSelection :: !Selection !Selection -> [Selection]
changeSelection oldSelection newSelection 
	= normalise (changeSelection` oldSelection newSelection)
where
	normalise = filter (notEmptySelection)

	changeSelection` :: Selection Selection -> [Selection]
	changeSelection` old new
		# old = orderSelection old
		# new = orderSelection new
		// completely the same => redraw nothing
		| old.start == new.start && old.end == new.end
			= []
		// selections do not overlap => redraw both
		| old.end <= new.start || old.start >= new.end
			= [ old, new ]
		// otherwise, redraw two fragments
		=	[ orderSelection { start = old.start,	end = new.start }
			, orderSelection { start = old.end,	end = new.end	}
			]

selectLines :: !Int !Int !Text -> Selection
selectLines bound1 bound2 text
  | last >= textLength text - 1
    = {start={col=0,row=first},end={col=size (fst (getLine last text)), row=last}}
    = {start={col=0,row=first},end={col=0,row=last+1}}
  where
    first = min bound1 bound2
    last  = max bound1 bound2

validateSelection :: !Selection Text -> Selection
validateSelection {start,end} text
	= {start = {start & row = startrow}, end = {end & row = endrow}}
where
	startrow = validateLineNr start.row text
	endrow = validateLineNr end.row text