diff --git a/fcore/text-builder.sml b/fcore/text-builder.sml index fd385b7..164d0d3 100644 --- a/fcore/text-builder.sml +++ b/fcore/text-builder.sml @@ -324,6 +324,16 @@ struct in absIdx >= searchIdx + searchLen end + fun advanceSearchPos (absIdx, searchPos, searchHd, searchLen) = + let + val searchIdx = Vector.sub (searchHd, searchPos) + in + if absIdx >= searchIdx andalso absIdx < searchIdx + searchLen then + searchPos + else + searchPos + 1 + end + fun buildTextStringSearch ( pos , str @@ -357,158 +367,43 @@ struct , bgAcc , env ) - else if pos < String.size str then - case String.sub (str, pos) of - #" " => - (* if inside cursor, then create cursorAcc; - * else, just skip as usual *) - if absIdx <> cursorPos then - (* not in cursur *) - if isInSearchRange (absIdx, searchPos, searchHd, searchLen) then - (* draw *) - let - (* todo: temp colours *) - val r: Real32.real = 0.3 - val g: Real32.real = 0.1 - val b: Real32.real = 0.1 - val {fw, fh, ...} = env + else + let + val searchPos = + advanceSearchPos (absIdx, searchPos, searchHd, searchLen) + in + if searchPos = Vector.length searchHd then + (* exhausted search list so call normal build function *) + buildTextString + ( pos + , str + , acc + , posX + , posY + , startX + , tl + , absIdx + , cursorPos + , cursorAcc + , bgAcc + , env + ) - val space = makeRect (posX, posY, fw, fh, r, g, b) - val bgAcc = space :: bgAcc - in - buildTextStringSearch - ( pos + 1 - , str - , acc - , posX + xSpace - , posY - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - end - else - buildTextStringSearch - ( pos + 1 - , str - , acc - , posX + xSpace - , posY - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - else - (* in cursor *) - let - val {fw, fh, r, g, b, ...} = env - - val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) - in - buildTextStringSearch - ( pos + 1 - , str - , acc - , posX + xSpace - , posY - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - end - | #"\n" => - if posY + ySpace < #h env then - if absIdx <> cursorPos then - (* not in cursor position, so iterate like normal *) - buildTextStringSearch - ( pos + 1 - , str - , acc - , startX - , posY + ySpace - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - else - (* in cursor position, so build cursorAcc *) - let - val {fw, fh, r, g, b, ...} = env - - val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) - in - buildTextStringSearch - ( pos + 1 - , str - , acc - , startX - , posY + ySpace - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - end - else - accToDrawMsg (acc, cursorAcc, bgAcc, env) - | chr => - let - val chrFun = Vector.sub (CozetteAscii.asciiTable, Char.ord chr) - in - if absIdx <> cursorPos then - (* not equal to cursor *) - if posX + xSpace < #w env then + else if pos < String.size str then + case String.sub (str, pos) of + #" " => + (* if inside cursor, then create cursorAcc; + * else, just skip as usual *) + if absIdx <> cursorPos then + (* not in cursur *) if isInSearchRange (absIdx, searchPos, searchHd, searchLen) then + (* draw *) let - val {fw, fh, ...} = env - (* todo: temp colours *) - val r: Real32.real = 0.7 - val g: Real32.real = 0.7 - val b: Real32.real = 0.7 - - (* build char vec *) - val chrVec = makeChr (chr, posX, posY, fw, fh, r, g, b) - val acc = chrVec :: acc - - (* build cursor (behind text) vec *) val r: Real32.real = 0.3 val g: Real32.real = 0.1 val b: Real32.real = 0.1 + val {fw, fh, ...} = env val space = makeRect (posX, posY, fw, fh, r, g, b) val bgAcc = space :: bgAcc @@ -532,50 +427,36 @@ struct ) end else - let - val {fw, fh, r, g, b, ...} = env - - val chrVec = makeChr (chr, posX, posY, fw, fh, r, g, b) - val acc = chrVec :: acc - val searchPos = - if - isAfterSearchRange - (absIdx, searchPos, searchHd, searchLen) - then searchPos + 1 - else searchPos - in - buildTextStringSearch - ( pos + 1 - , str - , acc - , posX + xSpace - , posY - , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - end - else if posY + ySpace < #h env then + buildTextStringSearch + ( pos + 1 + , str + , acc + , posX + xSpace + , posY + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + else + (* in cursor *) let val {fw, fh, r, g, b, ...} = env - val chrVec = makeChr - (chr, startX, posY + ySpace, fw, fh, r, g, b) - val acc = chrVec :: acc + val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) in buildTextStringSearch ( pos + 1 , str , acc - , startX + xSpace - , posY + ySpace + , posX + xSpace + , posY , startX , tl , absIdx + 1 @@ -588,52 +469,39 @@ struct , searchLen ) end - else - accToDrawMsg (acc, cursorAcc, bgAcc, env) - else - (* equal to cursor *) - let - val {fw, fh, r, g, b, hr, hg, hb, ...} = env - val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) - in - if posX + xSpace < #w env then + | #"\n" => + if posY + ySpace < #h env then + if absIdx <> cursorPos then + (* not in cursor position, so iterate like normal *) + buildTextStringSearch + ( pos + 1 + , str + , acc + , startX + , posY + ySpace + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + else + (* in cursor position, so build cursorAcc *) let - val chrVec = makeChr (chr, posX, posY, fw, fh, hr, hg, hb) - val acc = chrVec :: acc + val {fw, fh, r, g, b, ...} = env + + val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) in - (* can start building after cursor now, - * since cursor was built *) buildTextStringSearch ( pos + 1 , str , acc - , posX + xSpace - , posY , startX - , tl - , absIdx + 1 - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - end - else if posY + ySpace < #h env then - let - val chrVec = makeChr - (chr, startX, posY + ySpace, fw, fh, hr, hg, hb) - val acc = chrVec :: acc - in - (* can start building after cursor now, - * since cursor was built *) - buildTextStringSearch - ( pos + 1 - , str - , acc - , startX + xSpace , posY + ySpace , startX , tl @@ -647,32 +515,192 @@ struct , searchLen ) end + else + accToDrawMsg (acc, cursorAcc, bgAcc, env) + | chr => + let + val chrFun = Vector.sub (CozetteAscii.asciiTable, Char.ord chr) + in + if absIdx <> cursorPos then + (* not equal to cursor *) + if posX + xSpace < #w env then + if isInSearchRange (absIdx, searchPos, searchHd, searchLen) then + let + val {fw, fh, ...} = env + + (* todo: temp colours *) + val r: Real32.real = 0.7 + val g: Real32.real = 0.7 + val b: Real32.real = 0.7 + + (* build char vec *) + val chrVec = makeChr (chr, posX, posY, fw, fh, r, g, b) + val acc = chrVec :: acc + + (* build cursor (behind text) vec *) + val r: Real32.real = 0.3 + val g: Real32.real = 0.1 + val b: Real32.real = 0.1 + + val space = makeRect (posX, posY, fw, fh, r, g, b) + val bgAcc = space :: bgAcc + in + buildTextStringSearch + ( pos + 1 + , str + , acc + , posX + xSpace + , posY + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + end + else + let + val {fw, fh, r, g, b, ...} = env + + val chrVec = makeChr (chr, posX, posY, fw, fh, r, g, b) + val acc = chrVec :: acc + in + buildTextStringSearch + ( pos + 1 + , str + , acc + , posX + xSpace + , posY + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + end + else if posY + ySpace < #h env then + let + val {fw, fh, r, g, b, ...} = env + + val chrVec = makeChr + (chr, startX, posY + ySpace, fw, fh, r, g, b) + val acc = chrVec :: acc + in + buildTextStringSearch + ( pos + 1 + , str + , acc + , startX + xSpace + , posY + ySpace + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + end + else + accToDrawMsg (acc, cursorAcc, bgAcc, env) else - accToDrawMsg (acc, cursorAcc, bgAcc, env) + (* equal to cursor *) + let + val {fw, fh, r, g, b, hr, hg, hb, ...} = env + val cursorAcc = makeRect (posX, posY, fw, fh, r, g, b) + in + if posX + xSpace < #w env then + let + val chrVec = makeChr + (chr, posX, posY, fw, fh, hr, hg, hb) + val acc = chrVec :: acc + in + (* can start building after cursor now, + * since cursor was built *) + buildTextStringSearch + ( pos + 1 + , str + , acc + , posX + xSpace + , posY + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + end + else if posY + ySpace < #h env then + let + val chrVec = makeChr + (chr, startX, posY + ySpace, fw, fh, hr, hg, hb) + val acc = chrVec :: acc + in + (* can start building after cursor now, + * since cursor was built *) + buildTextStringSearch + ( pos + 1 + , str + , acc + , startX + xSpace + , posY + ySpace + , startX + , tl + , absIdx + 1 + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + end + else + accToDrawMsg (acc, cursorAcc, bgAcc, env) + end end - end - else - (* change to searching in string's tl *) - case tl of - hd :: tl => - buildTextStringSearch - ( 0 - , hd - , acc - , posX - , posY - , startX - , tl - , absIdx - , cursorPos - , cursorAcc - , bgAcc - , env - , searchHd - , searchPos - , searchLen - ) - | [] => accToDrawMsg (acc, cursorAcc, bgAcc, env) + else + (* change to searching in string's tl *) + case tl of + hd :: tl => + buildTextStringSearch + ( 0 + , hd + , acc + , posX + , posY + , startX + , tl + , absIdx + , cursorPos + , cursorAcc + , bgAcc + , env + , searchHd + , searchPos + , searchLen + ) + | [] => accToDrawMsg (acc, cursorAcc, bgAcc, env) + end (* gets line start idx, relative to right hd *) fun helpGetLineStartIdx (startLine, curLine, rLnHd) = diff --git a/shell/shell.sml b/shell/shell.sml index 0d6d1d1..f65eef4 100644 --- a/shell/shell.sml +++ b/shell/shell.sml @@ -69,7 +69,7 @@ struct let val buffer = #buffer app val buffer = LineGap.goToStart buffer - val searchString = "val " + val searchString = "abc" val searchList = SearchList.build (buffer, searchString) val buffer = LineGap.goToStart buffer in diff --git a/temp.txt b/temp.txt index d6ea8a2..db2fcbc 100644 --- a/temp.txt +++ b/temp.txt @@ -1,542 +1 @@ -signature TEXT_BUILDER = -aaron baron carrot durian - (* Prerequisite: LineGap is moved to requested line first. *) - val build: int * int * LineGap.t * int * int - -> MailboxType.t list -end - - - -structure TextBuilder :> TEXT_BUILDER = -struct - val xSpace = 13 - val xSpace3 = xSpace * 3 - val ySpace = 25 - val fontSize = 30.0 - - fun accToDrawMsg (textAcc, cursorAcc) = - let - open MailboxType - open DrawMsg - - val textAcc = Vector.concat textAcc - val cursorAcc = Vector.concat cursorAcc - - val textMsg = REDRAW_TEXT textAcc - val cursorMsg = REDRAW_CURSOR cursorAcc - in - [DRAW textMsg, DRAW cursorMsg] - end - - fun buildCursor (posX, posY, fWindowWidth, fWindowHeight, r, g, b) = - let - val left = posX + 9 - val left = Real32.fromInt left - val right = left + 12.0 - - val top = Real32.fromInt posY - val bottom = top + fontSize + 2.0 - - val halfHeight = fWindowHeight / 2.0 - val top = (~(top - halfHeight)) / halfHeight - val bottom = (~(bottom - halfHeight)) / halfHeight - - val halfWidth = fWindowWidth / 2.0 - val left = (left - halfWidth) / halfWidth - val right = (right - halfWidth) / halfWidth - - val vec = - #[ left, top, r, g, b - , right, top, r, g, b - , left, bottom, r, g, b - - , left, bottom, r, g, b - , right, bottom, r, g, b - , right, top, r, g, b - ] - in - [vec] - end - - (* builds text from a string with char-wrap. - * char-wrap is a similar concept to word-wrap, - * but it breaks on character in the middle of a word. - * - * Will likely want multiple versions of these two mutually recursive - * functions for each selection and cursor type: - * cursor over an individual character, - * range selection where multiple characters are selected, etc. - * - * Todo: - * - Possibly add visual horizontal indentation when char-wrap occurs - * on an indented line *) - fun buildTextStringAfterCursor - ( pos, str, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) = - if pos < String.size str then - case String.sub (str, pos) of - #" " => - (* if space, then proceed forward one char - * without adding to acc *) - buildTextStringAfterCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - | #"\t" => - (* if tab, proceed forward one char, - * and jump visually forwards three chars *) - buildTextStringAfterCursor - ( pos + 1, str, acc, posX + xSpace3, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - | #"\n" => - (* if \n, move down vertically, and move to start horizontally - * assuming we have not exceeded the window's height. - * If we have exceeded the window's height, just return acc. *) - if posY + ySpace < windowHeight then - buildTextStringAfterCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - else - (* return if there is no more vertical space after line break *) - accToDrawMsg (acc, cursorAcc) - | #"\r" => - (* same as \n, except we also check if we are in a \r\n pair, - * and proceed two characters forward if so *) - if posY + ySpace < windowHeight then - if - pos < String.size str - 1 - andalso String.sub (str, pos + 1) = #"\n" - then - buildTextStringAfterCursor - ( pos + 2, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - else - buildTextStringAfterCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - else - (* return if there is no more vertical space after line break *) - accToDrawMsg (acc, cursorAcc) - | chr => - (* for any other character, add it to acc if there is space, - * and proceed forward one character in the string *) - let - val chrFun = Vector.sub (CozetteAscii.asciiTable, Char.ord chr) - in - if posX + xSpace < windowWidth then - (* if there is horizontal space, place char on the right *) - let - val chrVec = chrFun - (posX, posY, fontSize, fontSize, fWindowWidth, fWindowHeight, r, g, b) - val acc = chrVec :: acc - in - buildTextStringAfterCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end - else if posY + ySpace < windowHeight then - (* if there is vertical space, place char down below at startX *) - let - val chrVec = chrFun - ( startX, posY + ySpace, fontSize, fontSize - , fWindowWidth, fWindowHeight - , r, g, b - ) - val acc = chrVec :: acc - in - buildTextStringAfterCursor - ( pos + 1, str, acc, startX + xSpace, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end - else - (* return if no space horizontally or vertically *) - accToDrawMsg (acc, cursorAcc) - end - else - (* if we reached the end of the string, - * call function to build next string *) - continueBuildTextLineGapAfterCursor - ( tl, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, cursorAcc - ) - - and continueBuildTextLineGapAfterCursor - ( strList, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, cursorAcc - ) = - case strList of - hd :: tl => - buildTextStringAfterCursor - ( 0, hd, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - | [] => accToDrawMsg (acc, cursorAcc) - - (* same as buildTextStringAfterCursor, except this keeps track of absolute - * index and cursor pos too *) - fun buildTextStringBeforeCursor - ( pos, str, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx, cursorPos, hr, hg, hb - ) = - if pos < String.size str then - case String.sub (str, pos) of - #" " => - buildTextStringBeforeCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - | #"\t" => - buildTextStringBeforeCursor - ( pos + 1, str, acc, posX + xSpace3, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - | #"\n" => - if posY + ySpace < windowHeight then - buildTextStringBeforeCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - else - accToDrawMsg (acc, []) - | #"\r" => - if posY + ySpace < windowHeight then - if - pos < String.size str - 1 - andalso String.sub (str, pos + 1) = #"\n" - then - buildTextStringBeforeCursor - ( pos + 2, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 2, cursorPos, hr, hg, hb - ) - else - buildTextStringBeforeCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - else - accToDrawMsg (acc, []) - | chr => - let - val chrFun = Vector.sub (CozetteAscii.asciiTable, Char.ord chr) - in - if posX + xSpace < windowWidth then - let - val chrVec = chrFun - (posX, posY, fontSize, fontSize, fWindowWidth, fWindowHeight, r, g, b) - val acc = chrVec :: acc - in - buildTextStringBeforeCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - end - else if posY + ySpace < windowHeight then - let - val chrVec = chrFun - ( startX, posY + ySpace, fontSize, fontSize - , fWindowWidth, fWindowHeight - , r, g, b - ) - val acc = chrVec :: acc - in - buildTextStringBeforeCursor - ( pos + 1, str, acc, startX + xSpace, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, hr, hg, hb - ) - end - else - accToDrawMsg (acc, []) - end - else - continueBuildTextLineGapBeforeCursor - ( tl, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, absIdx, cursorPos, hr, hg, hb - ) - - and buildTextStringWithinCursor - ( pos, str, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx, cursorPos, cursorAcc, hr, hg, hb - ) = - if pos < String.size str then - case String.sub (str, pos) of - #" " => - (* if inside cursor, then create cursorAcc; - * else, just skip as usual *) - if absIdx <> cursorPos then - (* not in cursur *) - buildTextStringWithinCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - else - (* in cursor *) - let - val cursorAcc = buildCursor (posX, posY, fWindowWidth, fWindowHeight, r, g ,b) - in - buildTextStringAfterCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end - | #"\t" => - (* todo: draw cursor if cursor is on tab - * but this is not a priority right now *) - buildTextStringWithinCursor - ( pos + 1, str, acc, posX + xSpace3, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - | #"\n" => - if posY + ySpace < windowHeight then - if absIdx <> cursorPos then - (* not in cursor position, so iterate like normal *) - buildTextStringWithinCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - else - (* in cursor position, so build cursorAcc - * and call AfterCursor function *) - 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" => - if posY + ySpace < windowHeight then - if - pos < String.size str - 1 - andalso String.sub (str, pos + 1) = #"\n" - then - buildTextStringWithinCursor - ( pos + 2, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 2, cursorPos, cursorAcc, hr, hg, hb - ) - else - buildTextStringWithinCursor - ( pos + 1, str, acc, startX, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - else - accToDrawMsg (acc, cursorAcc) - | chr => - let - val chrFun = Vector.sub (CozetteAscii.asciiTable, Char.ord chr) - in - if absIdx <> cursorPos then - (* not equal to cursor *) - if posX + xSpace < windowWidth then - let - val chrVec = chrFun - (posX, posY, fontSize, fontSize, fWindowWidth, fWindowHeight, r, g, b) - val acc = chrVec :: acc - in - buildTextStringWithinCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - end - else if posY + ySpace < windowHeight then - let - val chrVec = chrFun - ( startX, posY + ySpace, fontSize, fontSize - , fWindowWidth, fWindowHeight - , r, g, b - ) - val acc = chrVec :: acc - in - buildTextStringWithinCursor - ( pos + 1, str, acc, startX + xSpace, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx + 1, cursorPos, cursorAcc, hr, hg, hb - ) - end - else - accToDrawMsg (acc, cursorAcc) - else - (* equal to cursor *) - let - val cursorAcc = buildCursor (posX, posY, fWindowWidth, fWindowHeight, r, g ,b) - in - if posX + xSpace < windowWidth then - let - val chrVec = chrFun - ( posX, posY, fontSize, fontSize - , fWindowWidth, fWindowHeight - , hr, hg, hb - ) - val acc = chrVec :: acc - in - (* can start building after cursor now, - * since cursor was built *) - buildTextStringAfterCursor - ( pos + 1, str, acc, posX + xSpace, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end - else if posY + ySpace < windowHeight then - let - val chrVec = chrFun - ( startX, posY + ySpace, fontSize, fontSize - , fWindowWidth, fWindowHeight - , hr, hg, hb - ) - val acc = chrVec :: acc - in - (* can start building after cursor now, - * since cursor was built *) - buildTextStringAfterCursor - ( pos + 1, str, acc, startX + xSpace, posY + ySpace, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, cursorAcc - ) - end - else - accToDrawMsg (acc, cursorAcc) - end - end - - else - (* we have built cursor now, so can call after-cursor function - * to build rest of text *) - continueBuildTextLineGapAfterCursor - ( tl, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, cursorAcc - ) - - and continueBuildTextLineGapBeforeCursor - ( strList, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, absIdx, cursorPos, hr, hg, hb - ) = - case strList of - hd :: tl => - if cursorPos >= absIdx + cursorPos then - (* if end of string is before cursor *) - buildTextStringBeforeCursor - ( 0, hd, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx, cursorPos, hr, hg, hb - ) - else - (* if within cursor *) - buildTextStringWithinCursor - ( 0, hd, acc, posX, posY, startX - , windowWidth, windowHeight, fWindowWidth, fWindowHeight - , r, g, b, tl, absIdx, cursorPos, [], hr, hg, hb - ) - | [] => accToDrawMsg (acc, []) - - fun build - (startLine, cursorPos, lineGap: LineGap.t, windowWidth, windowHeight) = - let - val lineGap = LineGap.goToLine (startLine, lineGap) - val {rightStrings, rightLines, line = curLine, idx = curIdx, ...} = lineGap - in - case (rightStrings, rightLines) of - (rStrHd :: rStrTl, rLnHd :: _) => - let - (* get index of line to start building from *) - val startIdx = - if startLine > curLine then - let - val lnPos = startLine - curLine - 1 - val startIdx = Vector.sub (rLnHd, lnPos) - in - if - String.sub (rStrHd, startIdx) = #"\r" - andalso startIdx < String.size rStrHd - 1 - andalso String.sub (rStrHd, startIdx + 1) = #"\n" - then - (* handle \r\n pair *) - startIdx + 2 - else startIdx + 1 - end - else - 0 - - val absIdx = curIdx + startIdx - - in - if cursorPos < curIdx + String.size rStrHd then - (* if cursor is within string *) - buildTextStringWithinCursor - ( startIdx, rStrHd, [] - , 5, 5, 5 - , windowWidth, windowHeight - , Real32.fromInt windowWidth, Real32.fromInt windowHeight - , 0.67, 0.51, 0.83 - , rStrTl, absIdx, cursorPos, [] - , 0.211, 0.219, 0.25 - ) - else - (* if cursor is after string *) - buildTextStringBeforeCursor - ( startIdx, rStrHd, [] - , 5, 5, 5 - , windowWidth, windowHeight - , Real32.fromInt windowWidth, Real32.fromInt windowHeight - , 0.67, 0.51, 0.83 - , rStrTl, absIdx, cursorPos - , 0.211, 0.219, 0.25 - ) - end - | (_, _) => - (* requested line goes beyond the buffer, - * so just return empty list as there is nothig - * else we can do. *) - [] - end -end +abcabc