diff --git a/fcore/cursor.sml b/fcore/cursor.sml index bfd17a0..7548497 100644 --- a/fcore/cursor.sml +++ b/fcore/cursor.sml @@ -1,58 +1,72 @@ structure Cursor = struct - (* todo: viL does not handle \r\n pair right now - * but this is not a priority so it's okay *) - local - fun helpVilLf (hd, strIdx, bufferIdx, cursorIdx, tl) = - (* if we are in \n, - * move cursor to character after newline - * if possible *) - if strIdx < String.size hd - 3 then - (* we know it is safe to move cursorIdx by 2 - * if strIdx + 2 is before or at the end of the string. *) - cursorIdx + 2 - else - (* we have to check the tl to see if it is not empty - * so we know it is safe to move. *) - case tl of - _ :: _ => - (* not empty, so we can increment by 2 *) - cursorIdx + 2 - | [] => - (* empty, so return end of string which is \n *) - bufferIdx + String.size hd - 1 - in - (* Prerequisite: lineGap is moved to requested idx first - * todo: check if we are in a \r\n pair, but this is not a priority *) - fun viL (lineGap: LineGap.t, cursorIdx) = - let - val {rightStrings, idx = bufferIdx, ...} = lineGap - in - case rightStrings of - hd :: tl => - let - (* convert absolute cursorIdx to idx relative to hd string *) - val strIdx = cursorIdx - bufferIdx - in - if strIdx < String.size hd - 2 then - (case String.sub (hd, strIdx + 1) of - #"\n" => helpVilLf (hd, strIdx, bufferIdx, cursorIdx, tl) + (* Prerequisite: lineGap is moved to requested idx first + * todo: check if we are in a \r\n pair, but this is not a priority *) + fun viL (lineGap: LineGap.t, cursorIdx) = + let + val {rightStrings, idx = bufferIdx, ...} = lineGap + in + case rightStrings of + hd :: tl => + let + (* convert absolute cursorIdx to idx relative to hd string *) + val strIdx = cursorIdx - bufferIdx + in + if strIdx + 1 < String.size hd then + (* if there is at least one character after this idx *) + let + val nextChr = String.sub (hd, strIdx + 1) + in + (case nextChr of + #"\n" => + if strIdx + 2 < String.size hd then + (* if there are at least two chars after strIdx *) + cursorIdx + 2 + else + (* only one char after strIdx which is \n + * if there is a string at the tl, can increment by 2 *) + (case tl of + _ :: _ => cursorIdx + 2 + | [] => cursorIdx + 1) | _ => cursorIdx + 1) - else - (case tl of - tlhd :: tltl => - (* if there is another string after current head, we can increment cursorIdx - * however, first we need to check if next char is \n. *) - (case String.sub (tlhd, 0) of - #"\n" => helpVilLf (tlhd, 0, bufferIdx, cursorIdx, tltl) - | _ => cursorIdx + 1) - | _ => - (* if there is no string after current head, return original cursorIdx *) - cursorIdx) - end - | [] => - (* return original cursorIdx if there is nothing to the right *) - cursorIdx - end - end + end + else + (* no chars after this idx; have to check tl *) + (case tl of + tlhd :: tltl => + (* if there is another string after current head, we can increment cursorIdx + * however, first we need to check if next char is \n. *) + let + val nextChr = String.sub (tlhd, 0) + in + (case nextChr of + #"\n" => + if String.size tlhd > 2 then + (* if there is at least one character after \n + * then increment cursorIdx by 2 *) + cursorIdx + 2 + else + (* this string only contains \n + * but there is a small possibility tltl + * contains another string. + * If it does, we can increment cursorIdx by 2, + * moving past newline. + * If not, increment cursorIdx by 1, + * landing on newline. *) + (case tltl of + tltlhd :: _ => cursorIdx + 2 + | [] => cursorIdx + 1) + | _ => + (* next char is not newline, + * so we can just increment by 1 *) + cursorIdx + 1) + end + | [] => + (* if there is no string after current head, return original cursorIdx *) + cursorIdx) + end + | [] => + (* return original cursorIdx if there is nothing to the right *) + cursorIdx + end end diff --git a/fcore/text-builder.sml b/fcore/text-builder.sml index 0b0389e..cc99065 100644 --- a/fcore/text-builder.sml +++ b/fcore/text-builder.sml @@ -326,15 +326,25 @@ struct else (* in cursor position, so build cursorAcc * and call AfterCursor function *) - let - val cursorAcc = buildCursor (posX, posY, fWindowWidth, fWindowHeight, r, g ,b) - in - buildTextStringAfterCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end + if pos = String.size str - 1 andalso tl = [] then + (* if we are at end of lineGap, we want to build cursorAcc + * at different coordinates than usual *) + let + val cursorAcc = + buildCursor (startX, posY + ySpace, fWindowWidth, fWindowHeight, r, g, b) + in + accToDrawMsg (acc, cursorAcc) + end + else + let + val cursorAcc = buildCursor (posX, posY, fWindowWidth, fWindowHeight, r, g ,b) + in + buildTextStringAfterCursor + ( pos + 1, str, acc, startX, posY + ySpace, startX + , windowWidth, windowHeight, fWindowWidth, fWindowHeight + , r, g, b, tl, cursorAcc + ) + end else accToDrawMsg (acc, cursorAcc) | #"\r" => diff --git a/shf b/shf index b31941f..14103cc 100755 Binary files a/shf and b/shf differ diff --git a/temp.txt b/temp.txt index 49dd153..7ffeab5 100644 --- a/temp.txt +++ b/temp.txt @@ -5,4 +5,3 @@ sig val build: int * int * LineGap.t * int * int -> MailboxType.t list enda -