diff --git a/fcore/normal-mode/normal-finish.sml b/fcore/normal-mode/normal-finish.sml index 7b77dda..38c75c3 100644 --- a/fcore/normal-mode/normal-finish.sml +++ b/fcore/normal-mode/normal-finish.sml @@ -12,20 +12,24 @@ struct fun buildTextAndClear (app: app_type, buffer, cursorIdx, searchList, msgs, bufferModifyTime) = let - val {windowWidth, windowHeight, startLine, searchString, - visualScrollColumn = prevScrollColumn, ...} = app + val + { windowWidth + , windowHeight + , searchString + , visualScrollColumn = prevScrollColumn + , startLine = prevLineNumber + , ... + } = app - (* calculate scroll column *) + (* calculate new scroll column and start line, if there are any changes *) val buffer = LineGap.goToIdx (cursorIdx, buffer) val visualScrollColumn = - TextScroll.getScrollColumn (buffer, cursorIdx, windowWidth, prevScrollColumn) + TextScroll.getScrollColumn + (buffer, cursorIdx, windowWidth, prevScrollColumn) - (* move LineGap to first line displayed on screen *) - val buffer = LineGap.goToLine (startLine, buffer) - - (* get new startLine which may move screen depending on cursor movements *) - val startLine = TextWindow.getStartLine - (buffer, startLine, cursorIdx, windowWidth, windowHeight) + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, windowHeight) (* move buffer to new startLine as required by TextBuilder.build *) val buffer = LineGap.goToLine (startLine, buffer) @@ -93,7 +97,8 @@ struct val newBuffer = LineGap.goToIdx (cursorIdx, buffer) val visualScrollColumn = - TextScroll.getScrollColumn (buffer, cursorIdx, newWidth, prevScrollColumn) + TextScroll.getScrollColumn + (buffer, cursorIdx, newWidth, prevScrollColumn) val newBuffer = LineGap.goToLine (startLine, newBuffer) val lineIdx = TextBuilderUtils.getLineAbsIdxFromBuffer (startLine, buffer) @@ -123,69 +128,14 @@ struct ) end - (* Difference between this and buildTextAndClear is that - * this is meant to be called after a chr movement, - * where the cursor may possibly jump off window by a wide marigin. - * Since the cursor may move away a lot, it is best to recenter. - * *) - fun buildTextAndClearAfterChr - (app: app_type, buffer, cursorIdx, searchList, initialMsg, bufferModifyTime) : - AppType.app_type = - let - val {windowWidth, windowHeight, startLine, searchString, visualScrollColumn - = prevScrollColumn, ...} = app - - val buffer = LineGap.goToIdx (cursorIdx, buffer) - val visualScrollColumn = - TextScroll.getScrollColumn (buffer, cursorIdx, windowWidth, prevScrollColumn) - - (* move LineGap to first line displayed on screen *) - val buffer = LineGap.goToLine (startLine, buffer) - - (* get new startLine which may move screen depending on cursor movements *) - val startLine = TextWindow.getStartLine - (buffer, startLine, cursorIdx, windowWidth, windowHeight) - - (* move buffer to new startLine as required by TextBuilder.build - * and move searchList to idx where line starts as well *) - val buffer = LineGap.goToLine (startLine, buffer) - - val drawMsg = NormalModeTextBuilder.build - ( startLine - , cursorIdx - , buffer - , windowWidth - , windowHeight - , searchList - , searchString - , visualScrollColumn - ) - val drawMsg = Vector.concat drawMsg - val drawMsg = DRAW_TEXT drawMsg - val msgs = DRAW drawMsg :: initialMsg - - val mode = NORMAL_MODE "" - in - NormalModeWith.bufferAndCursorIdx - ( app - , buffer - , cursorIdx - , mode - , startLine - , searchList - , msgs - , bufferModifyTime - , visualScrollColumn - ) - end - + (* todo: check; the way we get the startLine is almost certainly wrong *) fun centreToCursor (app: app_type) = let val { buffer , windowWidth , windowHeight - , startLine = origLine + , startLine = prevLineNumber , cursorIdx , searchList , searchString @@ -193,10 +143,11 @@ struct , visualScrollColumn , ... } = app - val buffer = LineGap.goToIdx (cursorIdx, buffer) - val startLine = TextWindow.getStartLineWithCursorCentered - (buffer, cursorIdx, origLine, windowWidth, windowHeight div 2) + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, windowHeight div 2) val buffer = LineGap.goToLine (startLine, buffer) val drawMsg = NormalModeTextBuilder.build @@ -213,20 +164,16 @@ struct val drawMsg = DRAW_TEXT drawMsg val drawMsg = [DRAW drawMsg] in - let - val _ = raise Fail "centering to line is unimplemented\n" - in - NormalModeWith.bufferAndCursorIdx - ( app - , buffer - , cursorIdx - , NORMAL_MODE "" - , startLine - , searchList - , drawMsg - , bufferModifyTime - , #visualScrollColumn app - ) - end + NormalModeWith.bufferAndCursorIdx + ( app + , buffer + , cursorIdx + , NORMAL_MODE "" + , startLine + , searchList + , drawMsg + , bufferModifyTime + , #visualScrollColumn app + ) end end diff --git a/fcore/normal-mode/normal-move.sml b/fcore/normal-mode/normal-move.sml index 147069b..0f51027 100644 --- a/fcore/normal-mode/normal-move.sml +++ b/fcore/normal-mode/normal-move.sml @@ -70,18 +70,11 @@ struct val buffer = LineGap.goToIdx (bufferIdx, buffer) val visualScrollColumn = - TextScroll.getScrollColumn (buffer, bufferIdx, windowWidth, prevScrollColumn) - val bufferLine = - let - val maxHeight = windowHeight - TextConstants.ySpace - in - TextWindow.getStartLineWithCursorCentered - (buffer, bufferIdx, bufferLine, windowWidth, maxHeight) - end + TextScroll.getScrollColumn + (buffer, bufferIdx, windowWidth, prevScrollColumn) + val bufferLine = let in raise Fail "todo: fix" end val buffer = LineGap.goToLine (bufferLine, buffer) - val lineIdx = - TextBuilderUtils.getLineAbsIdxFromBuffer (bufferLine, buffer) val drawMsg = NormalModeTextBuilder.build ( bufferLine @@ -121,7 +114,7 @@ struct { windowWidth , windowHeight , buffer - , startLine = origLine + , startLine = prevLineNumber , searchList , searchString , bufferModifyTime @@ -135,9 +128,12 @@ struct val buffer = LineGap.goToIdx (cursorIdx, buffer) val visualScrollColumn = - TextScroll.getScrollColumn (buffer, cursorIdx, windowWidth, prevScrollColumn) - val startLine = TextWindow.getStartLineWithCursorCentered - (buffer, cursorIdx, origLine, windowWidth, windowHeight div 2) + TextScroll.getScrollColumn + (buffer, cursorIdx, windowWidth, prevScrollColumn) + + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, windowHeight) val buffer = LineGap.goToLine (startLine, buffer) @@ -177,7 +173,7 @@ struct , cursorIdx , windowWidth , windowHeight - , startLine + , startLine = prevLineNumber , searchList , searchString , bufferModifyTime @@ -188,16 +184,16 @@ struct (* move LineGap and buffer to start of line *) val buffer = LineGap.goToIdx (cursorIdx, buffer) val cursorIdx = Cursor.matchPair (buffer, cursorIdx) - - val buffer = LineGap.goToLine (startLine, buffer) - val lineIdx = TextBuilderUtils.getLineAbsIdxFromBuffer (startLine, buffer) in let val buffer = LineGap.goToIdx (cursorIdx, buffer) val visualScrollColumn = - TextScroll.getScrollColumn (buffer, cursorIdx, windowWidth, prevScrollColumn) - val startLine = TextWindow.getStartLineWithCursorCentered - (buffer, cursorIdx, startLine, windowWidth, windowHeight div 2) + TextScroll.getScrollColumn + (buffer, cursorIdx, windowWidth, prevScrollColumn) + + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, windowHeight) val buffer = LineGap.goToLine (startLine, buffer) @@ -256,7 +252,7 @@ struct fun helpMoveToChr (app: app_type, buffer, cursorIdx, count, fMove, chr) = if count = 0 then - NormalFinish.buildTextAndClearAfterChr + NormalFinish.buildTextAndClear (app, buffer, cursorIdx, #searchList app, [], #bufferModifyTime app) else let @@ -288,7 +284,7 @@ struct if newCursorIdx = ~1 then NormalFinish.clearMode app else - NormalFinish.buildTextAndClearAfterChr + NormalFinish.buildTextAndClear (app, buffer, newCursorIdx, searchList, [], bufferModifyTime) end @@ -300,7 +296,7 @@ struct if newCursorIdx = ~1 then NormalFinish.clearMode app else - NormalFinish.buildTextAndClearAfterChr + NormalFinish.buildTextAndClear (app, buffer, newCursorIdx, searchList, [], bufferModifyTime) end end diff --git a/fcore/normal-mode/normal-search-finish.sml b/fcore/normal-mode/normal-search-finish.sml index 82921d7..4845889 100644 --- a/fcore/normal-mode/normal-search-finish.sml +++ b/fcore/normal-mode/normal-search-finish.sml @@ -9,12 +9,13 @@ struct val { buffer , cursorIdx - , startLine + , startLine = prevLineNumber , windowWidth , windowHeight , visualScrollColumn , ... } = app + val mode = NORMAL_SEARCH_MODE { searchString = searchString , tempSearchList = tempSearchList @@ -57,9 +58,11 @@ struct ) end + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, windowHeight) val buffer = LineGap.goToLine (startLine, buffer) - val startLine = TextWindow.getStartLine - (buffer, startLine, cursorIdx, windowWidth, windowHeight) val remainingWindowHeight = windowHeight - (TextConstants.ySpace * 2) @@ -92,8 +95,14 @@ struct , tempSearchList ) = let - val {buffer, cursorIdx, startLine, searchString, visualScrollColumn, ...} = - app + val + { buffer + , cursorIdx + , startLine = prevLineNumber + , searchString + , visualScrollColumn + , ... + } = app val floatWindowWidth = Real32.fromInt newWindowWidth val floatWindowHeight = Real32.fromInt newWindowHeight @@ -131,9 +140,11 @@ struct ) end + val buffer = LineGap.goToIdx (cursorIdx, buffer) + val cursorLine = LineGap.getLineNumberOfIdx (cursorIdx, buffer) + val startLine = + TextScroll.getStartLine (prevLineNumber, cursorLine, newWindowHeight) val buffer = LineGap.goToLine (startLine, buffer) - val startLine = TextWindow.getStartLine - (buffer, startLine, cursorIdx, newWindowWidth, newWindowHeight) val remainingWindowHeight = newWindowHeight - (TextConstants.ySpace * 2) diff --git a/fcore/normal-mode/normal-search-mode.sml b/fcore/normal-mode/normal-search-mode.sml index 6292cb1..4bf3f96 100644 --- a/fcore/normal-mode/normal-search-mode.sml +++ b/fcore/normal-mode/normal-search-mode.sml @@ -64,10 +64,6 @@ struct (* move LineGap to first line displayed on screen *) val buffer = LineGap.goToLine (startLine, buffer) - (* get new startLine which may move screen depending on cursor movements *) - val startLine = TextWindow.getStartLine - (buffer, startLine, cursorIdx, windowWidth, windowHeight) - (* move buffer to new startLine as required by TextBuilder.build *) val buffer = LineGap.goToLine (startLine, buffer) diff --git a/fcore/text-scroll.sml b/fcore/text-scroll.sml index cc46c7c..0732f21 100644 --- a/fcore/text-scroll.sml +++ b/fcore/text-scroll.sml @@ -34,12 +34,11 @@ struct (* cursorLine > prevLineNumber *) let val howManyLinesWeCanFit = windowHeight div TC.ySpace + val howManyLinesWeCanFit = howManyLinesWeCanFit - 2 in - if prevLineNumber + howManyLinesWeCanFit >= cursorLine then - prevLineNumber + if cursorLine > prevLineNumber + howManyLinesWeCanFit then + cursorLine - howManyLinesWeCanFit else - let val lineDifference = cursorLine - prevLineNumber - in prevLineNumber + lineDifference - end + prevLineNumber end end diff --git a/fcore/text-window.sml b/fcore/text-window.sml deleted file mode 100644 index ca565fc..0000000 --- a/fcore/text-window.sml +++ /dev/null @@ -1,452 +0,0 @@ -structure TextWindow = -struct - open TextConstants - - (* todo: at some point, make sure the functions in the TextWindow structure - * all act as if the screen is centered - * if the window width is more than 80 chars long *) - - fun getStartLineBefore (sIdx, shd, lineNum, absIdx, cursorIdx, stl) = - if sIdx < 0 then - case stl of - hd :: tl => - getStartLineBefore - (String.size hd - 1, hd, lineNum, absIdx, cursorIdx, tl) - | [] => 0 - else if absIdx = cursorIdx then - Int.max (lineNum - 1, 0) - else - let - val chr = String.sub (shd, sIdx) - in - if chr = #"\n" then - getStartLineBefore - (sIdx - 1, shd, lineNum - 1, absIdx - 1, cursorIdx, stl) - else - getStartLineBefore - (sIdx - 1, shd, lineNum, absIdx - 1, cursorIdx, stl) - end - - fun getStartLineAfter - ( sIdx - , shd - , lineNum - , absIdx - , cursorIdx - , stl - , maxWidth - , maxHeight - , curWidth - , curHeight - , origLine - ) = - if sIdx = String.size shd then - case stl of - hd :: tl => - getStartLineAfter - ( 0 - , hd - , lineNum - , absIdx - , cursorIdx - , tl - , maxWidth - , maxHeight - , curWidth - , curHeight - , origLine - ) - | [] => origLine - else if absIdx = cursorIdx then - origLine - else - let - val chr = String.sub (shd, sIdx) - in - if - chr = #"\n" - then - if curHeight + (ySpace * 3) >= maxHeight then - getStartLineAfter - ( sIdx + 1 - , shd - , lineNum + 1 - , absIdx + 1 - , cursorIdx - , stl - , maxWidth - , maxHeight - , 0 - , curHeight + ySpace - , origLine + 1 - ) - else - getStartLineAfter - ( sIdx + 1 - , shd - , lineNum + 1 - , absIdx + 1 - , cursorIdx - , stl - , maxWidth - , maxHeight - , 0 - , curHeight + ySpace - , origLine - ) - else if - curWidth + xSpace <= maxWidth - then - let - val curWidth = curWidth + xSpace - in - getStartLineAfter - ( sIdx + 1 - , shd - , lineNum - , absIdx + 1 - , cursorIdx - , stl - , maxWidth - , maxHeight - , curWidth - , curHeight - , origLine - ) - end - else (* have to create visual line break *) if - curHeight + (ySpace * 3) >= maxHeight - then - getStartLineAfter - ( sIdx + 1 - , shd - , lineNum + 1 - , absIdx + 1 - , cursorIdx - , stl - , maxWidth - , maxHeight - , 0 - , curHeight + ySpace - , origLine + 1 - ) - else - getStartLineAfter - ( sIdx + 1 - , shd - , lineNum + 1 - , absIdx + 1 - , cursorIdx - , stl - , maxWidth - , maxHeight - , 0 - , curHeight + ySpace - , origLine - ) - end - - (* Prerequisite: LineGap is moved to oldLine first. *) - fun getStartLine (lineGap: LineGap.t, oldLine, cursorIdx, maxWidth, maxHeight) = - let - val - { rightStrings - , rightLines - , line = curLine - , idx = curIdx - , leftStrings - , ... - } = lineGap - in - case (rightStrings, rightLines) of - (rStrHd :: rStrTl, rLnHd :: _) => - let - (* get index of line to start building from *) - val startIdx = - if oldLine > curLine then - let - val lnPos = oldLine - curLine - 1 - val startIdx = Vector.sub (rLnHd, lnPos) - in - startIdx - 1 - end - else - 0 - val absIdx = curIdx + startIdx - in - if cursorIdx < absIdx then - (* move upwards *) - getStartLineBefore - (startIdx, rStrHd, oldLine, absIdx, cursorIdx, leftStrings) - else if cursorIdx = absIdx + 1 then - (* double linebreak *) - getStartLineBefore - ( startIdx + 1 - , rStrHd - , oldLine - , absIdx + 1 - , cursorIdx - , leftStrings - ) - else if cursorIdx > absIdx then - (* possibly move downwards *) - getStartLineAfter - ( Int.max (startIdx, 0) - , rStrHd - , oldLine - , absIdx - , cursorIdx - , rStrTl - , maxWidth - , maxHeight - , 0 - , 0 - , oldLine - ) - else - (* keep current line *) - Int.max (oldLine - 1, 0) - end - | (_, _) => oldLine - end - - fun helpCentreCursor (strPos, str, lineNum, stl, maxW, halfH, curW, curH) = - if strPos < 0 then - case stl of - hd :: tl => - helpCentreCursor - (String.size hd - 1, hd, lineNum, tl, maxW, halfH, curW, curH) - | [] => (* return 0 for start of buffer *) 0 - else - let - val chr = String.sub (str, strPos) - in - if - chr = #"\n" - then - if curH + (ySpace * 3) >= halfH then - (* if we exceeded half the screen *) - lineNum - else - helpCentreCursor - (strPos - 1, str, lineNum - 1, stl, maxW, halfH, 0, curH + ySpace) - else if - curW + xSpace <= maxW - then - let - val curW = curW + xSpace - in - helpCentreCursor - (strPos - 1, str, lineNum, stl, maxW, halfH, curW + xSpace, curH) - end - else (* have to create visual line break *) if - curH + (ySpace * 3) >= halfH - then - (* if at limit, return current line lineNum *) - lineNum - else - helpCentreCursor - (strPos - 1, str, lineNum - 1, stl, maxW, halfH, 0, curH + ySpace) - end - - (* search for prev \n, and once found, - * call function to return startLine where cursor is centered *) - fun getCursorStartLine (strPos, str, lineNum, stl, maxW, halfH) = - if strPos < 0 then - case stl of - hd :: tl => - getCursorStartLine (String.size hd - 1, hd, lineNum, tl, maxW, halfH) - | [] => 0 - else - let - val chr = String.sub (str, strPos) - in - if chr = #"\n" then - (* \n found *) - helpCentreCursor - (strPos - 1, str, lineNum - 1, stl, maxW, halfH, xSpace, ySpace) - else - getCursorStartLine (strPos - 1, str, lineNum, stl, maxW, halfH) - end - - fun getLineNum (strIdx, lhd, bufferLine) = - if Vector.length lhd = 0 then - bufferLine - else if Vector.length lhd = 1 then - let val lineIdx = Vector.sub (lhd, 0) - in if lineIdx < strIdx then bufferLine + 1 else bufferLine - end - else - let - val firstLineIdx = Vector.sub (lhd, 0) - in - if firstLineIdx > strIdx then - bufferLine - else if firstLineIdx < strIdx then - BinSearch.equalOrLess (strIdx - 1, lhd) + bufferLine - else - bufferLine + 1 - end - - (* Prerequisite: LineGap is moved to cursor *) - fun getStartLineWithCursorCentered - (lineGap: LineGap.t, cursorIdx, origLine, maxWidth, maxHeight) = - let - val - { rightStrings - , rightLines - , idx = bufferIdx - , line = bufferLine - , leftStrings - , ... - } = lineGap - in - case (rightStrings, rightLines) of - (shd :: stl, lhd :: ltl) => - let - (* convert absolute cursorIdx to idx relative to hd string *) - val strIdx = cursorIdx - bufferIdx - in - if strIdx < String.size shd then - (* strIdx is in hd *) - let - val lineNum = getLineNum (strIdx, lhd, bufferLine) - in - getCursorStartLine - (strIdx, shd, lineNum, leftStrings, maxWidth, maxHeight) - end - else - (* strIdx is in tl *) - case (stl, ltl) of - (stlhd :: stltl, ltlhd :: _) => - let - val strIdx = strIdx - String.size shd - val bufferLine = bufferLine + Vector.length lhd - val lineNum = getLineNum (strIdx, ltlhd, bufferLine) - val leftStrings = shd :: leftStrings - in - getCursorStartLine - (strIdx, stlhd, lineNum, leftStrings, maxWidth, maxHeight) - end - | (_, _) => origLine - end - | (_, _) => origLine - end - - fun helpIsCursorVisible - (strPos, str, stl, absIdx, maxW, maxH, curW, curH, newCursorIdx) = - if strPos = String.size str then - case stl of - hd :: tl => - helpIsCursorVisible - (0, hd, tl, absIdx, maxW, maxH, curW, curH, newCursorIdx) - | [] => true - else if absIdx = newCursorIdx then - true - else - let - val chr = String.sub (str, strPos) - in - if - chr = #"\n" - then - if curH + (ySpace * 3) >= maxH then - false - else - helpIsCursorVisible - ( strPos + 1 - , str - , stl - , absIdx + 1 - , maxW - , maxH - , 0 - , curH + ySpace - , newCursorIdx - ) - else if - curW + xSpace <= maxW - then - helpIsCursorVisible - ( strPos + 1 - , str - , stl - , absIdx + 1 - , maxW - , maxH - , curW + xSpace - , curH - , newCursorIdx - ) - else (* have to create visual line break *) if - curH + (ySpace * 3) >= maxH - then - false - else - helpIsCursorVisible - ( strPos + 1 - , str - , stl - , absIdx + 1 - , maxW - , maxH - , 0 - , curH + ySpace - , newCursorIdx - ) - end - - fun startIsCursorVisible - (curIdx, shd, stl, lhd, startLine, curLine, maxW, maxH, newCursorIdx) = - if startLine = curLine then - helpIsCursorVisible (0, shd, stl, curIdx, maxW, maxH, 0, 0, newCursorIdx) - else - let - val relativeLine = (curLine + Vector.length lhd) - startLine - val lineIdx = Vector.sub (lhd, relativeLine) - val absIdx = curIdx + lineIdx - in - helpIsCursorVisible - (lineIdx, shd, stl, absIdx, maxW, maxH, 0, 0, newCursorIdx) - end - - (* Prerequisite: move LineGap.t to startLine *) - fun isCursorVisible (lineGap: LineGap.t, newCursorIdx, startLine, maxW, maxH) = - let - val {rightStrings, rightLines, line = curLine, idx = curIdx, ...} = - lineGap - in - case (rightStrings, rightLines) of - (shd :: stl, lhd :: ltl) => - if startLine < curLine + Vector.length lhd then - (* startLine in this node *) - startIsCursorVisible - ( curIdx - , shd - , stl - , lhd - , startLine - , curLine - , maxW - , maxH - , newCursorIdx - ) - else - (* startLine is in stl *) - (case (stl, ltl) of - (stlhd :: stltl, ltlhd :: ltltl) => - startIsCursorVisible - ( curIdx - , stlhd - , stltl - , ltlhd - , startLine - , curLine - , maxW - , maxH - , newCursorIdx - ) - | (_, _) => true) - | (_, _) => true - end -end diff --git a/lib/brolib-sml b/lib/brolib-sml index 5d2a2ef..737e869 160000 --- a/lib/brolib-sml +++ b/lib/brolib-sml @@ -1 +1 @@ -Subproject commit 5d2a2ef737b94bf3429c8af75eec46121712d675 +Subproject commit 737e8695e72b4984e8cc78b7d667cf86528c1b74 diff --git a/shf.mlb b/shf.mlb index 3452c68..7fd3f4f 100644 --- a/shf.mlb +++ b/shf.mlb @@ -44,7 +44,6 @@ fcore/text-builder/normal-mode-text-builder.sml fcore/text-builder.sml fcore/cursor.sml -fcore/text-window.sml fcore/text-scroll.sml fcore/normal-mode/normal-finish.sml