diff options
author | Kartik K. Agaram <vc@akkartik.com> | 2021-03-03 22:09:50 -0800 |
---|---|---|
committer | Kartik K. Agaram <vc@akkartik.com> | 2021-03-03 22:21:03 -0800 |
commit | 71e4f3812982dba2efb471283d310224e8db363e (patch) | |
tree | ea111a1acb8b8845dbda39c0e1b4bac1d198143b /linux/browse | |
parent | c6b928be29ac8cdb4e4d6e1eaa20420ff03e5a4c (diff) | |
download | mu-71e4f3812982dba2efb471283d310224e8db363e.tar.gz |
7842 - new directory organization
Baremetal is now the default build target and therefore has its sources at the top-level. Baremetal programs build using the phase-2 Mu toolchain that requires a Linux kernel. This phase-2 codebase which used to be at the top-level is now under the linux/ directory. Finally, the phase-2 toolchain, while self-hosting, has a way to bootstrap from a C implementation, which is now stored in linux/bootstrap. The bootstrap C implementation uses some literate programming tools that are now in linux/bootstrap/tools. So the whole thing has gotten inverted. Each directory should build one artifact and include the main sources (along with standard library). Tools used for building it are relegated to sub-directories, even though those tools are often useful in their own right, and have had lots of interesting programs written using them. A couple of things have gotten dropped in this process: - I had old ways to run on just a Linux kernel, or with a Soso kernel. No more. - I had some old tooling for running a single test at the cursor. I haven't used that lately. Maybe I'll bring it back one day. The reorg isn't done yet. Still to do: - redo documentation everywhere. All the README files, all other markdown, particularly vocabulary.md. - clean up how-to-run comments at the start of programs everywhere - rethink what to do with the html/ directory. Do we even want to keep supporting it? In spite of these shortcomings, all the scripts at the top-level, linux/ and linux/bootstrap are working. The names of the scripts also feel reasonable. This is a good milestone to take stock at.
Diffstat (limited to 'linux/browse')
-rw-r--r-- | linux/browse/README.md | 21 | ||||
-rw-r--r-- | linux/browse/main.mu | 394 | ||||
-rw-r--r-- | linux/browse/paginated-screen.mu | 661 | ||||
-rw-r--r-- | linux/browse/vimrc.vim | 2 |
4 files changed, 1078 insertions, 0 deletions
diff --git a/linux/browse/README.md b/linux/browse/README.md new file mode 100644 index 00000000..8f92b584 --- /dev/null +++ b/linux/browse/README.md @@ -0,0 +1,21 @@ +Render a subset of Markdown. + +To run: + + ``` + $ ./translate_mu apps/browse.mu + $ ./a.elf __text_file__ + ``` + +Press 'q' to quit. All other keys scroll down. + +## Format restrictions + +This is a fairly tiny subset of GitHub-Flavored Markdown. Things supported so +far: + +* Newlines are mostly ignored. Double newlines are rendered (paragraphs). + Newlines followed by indentation are rendered. +* Paragraphs starting with runs of `#` represent headings. +* Within a line, characters between `*`s or `_`s represent bolded text. No + italics. diff --git a/linux/browse/main.mu b/linux/browse/main.mu new file mode 100644 index 00000000..5b4f2e06 --- /dev/null +++ b/linux/browse/main.mu @@ -0,0 +1,394 @@ +fn main args-on-stack: (addr array addr array byte) -> _/ebx: int { + var args/eax: (addr array addr array byte) <- copy args-on-stack + var len/ecx: int <- length args + # if (len(args) <= 1) print usage and exit + compare len, 1 + { + break-if-> + print-string-to-real-screen "usage: browse [filename]\n" + print-string-to-real-screen " or browse test\n" + return 1 + } + # if (args[1] == "test") run-tests() + var tmp/ecx: (addr addr array byte) <- index args, 1 + var tmp2/eax: boolean <- string-equal? *tmp, "test" + compare tmp2, 0 + { + break-if-= + run-tests + return 0 # TODO: get at Num-test-failures somehow + } + # otherwise interactive mode + var args/eax: (addr array addr array byte) <- copy args-on-stack + var arg/eax: (addr addr array byte) <- index args, 1 + var filename/eax: (addr array byte) <- copy *arg + var file-storage: (handle buffered-file) + var file-storage-addr/esi: (addr handle buffered-file) <- address file-storage + open filename, 0, file-storage-addr + var fs/eax: (addr buffered-file) <- lookup file-storage + # if no file, exit + { + compare fs, 0 + break-if-!= + print-string-to-real-screen "file not found\n" + return 1 + } + # + interactive fs + return 0 +} + +fn interactive fs: (addr buffered-file) { + enable-screen-grid-mode + enable-keyboard-immediate-mode + # initialize screen state + var paginated-screen-storage: paginated-screen + var paginated-screen/eax: (addr paginated-screen) <- address paginated-screen-storage + initialize-paginated-screen paginated-screen, 0x40, 2, 5 + normal-text paginated-screen + # + { + render paginated-screen, fs + var key/eax: grapheme <- read-key-from-real-keyboard + compare key, 0x71/'q' + loop-if-!= + } + enable-keyboard-type-mode + enable-screen-type-mode +} + +fn render screen: (addr paginated-screen), fs: (addr buffered-file) { + start-drawing screen + render-normal screen, fs +} + +fn test-render-multicolumn-text { + # input text + var input-storage: (handle buffered-file) + var input-ah/eax: (addr handle buffered-file) <- address input-storage + populate-buffered-file-containing "abcdefgh", input-ah + var in/eax: (addr buffered-file) <- lookup input-storage + # output screen + var pg: paginated-screen + var pg-addr/ecx: (addr paginated-screen) <- address pg + initialize-fake-paginated-screen pg-addr, 3/rows, 6/cols, 2/page-width, 1/top-margin, 1/left-margin + # + render pg-addr, in + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen, 1, " ", "F - test-render-multicolumn-text/row1" + check-screen-row screen, 2, " ab ef", "F - test-render-multicolumn-text/row2" + check-screen-row screen, 3, " cd gh", "F - test-render-multicolumn-text/row3" +} + +fn test-render-heading-text { + # input text + var input-storage: (handle buffered-file) + var input-ah/eax: (addr handle buffered-file) <- address input-storage + populate-buffered-file-containing "# abc\n\ndef", input-ah + var in/eax: (addr buffered-file) <- lookup input-storage + # output screen + var pg: paginated-screen + var pg-addr/ecx: (addr paginated-screen) <- address pg + initialize-fake-paginated-screen pg-addr, 8/rows, 6/cols, 5/page-width, 1/top-margin, 1/left-margin + # + render pg-addr, in + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen, 1, " ", "F - test-render-heading-text/row1" + check-screen-row-in-color screen, 0xa0, 2, " abc ", "F - test-render-heading-text/heading" + check-screen-row screen, 3, " ", "F - test-render-heading-text/row3" + check-screen-row screen, 4, " def ", "F - test-render-heading-text/row4" +} + +fn test-render-bold-text { + # input text + var input-storage: (handle buffered-file) + var input-ah/eax: (addr handle buffered-file) <- address input-storage + populate-buffered-file-containing "a *b* c", input-ah + var in/eax: (addr buffered-file) <- lookup input-storage + # output screen + var pg: paginated-screen + var pg-addr/ecx: (addr paginated-screen) <- address pg + initialize-fake-paginated-screen pg-addr, 8/rows, 6/cols, 5/page-width, 1/top-margin, 1/left-margin + # + render pg-addr, in + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen, 2, " a b c", "F - test-render-bold-text/text" + check-screen-row-in-bold screen, 2, " b ", "F - test-render-bold-text/bold" +} + +# terminals don't always support italics, so we'll just always render italics +# as bold. +fn test-render-pseudoitalic-text { + # input text + var input-storage: (handle buffered-file) + var input-ah/eax: (addr handle buffered-file) <- address input-storage + populate-buffered-file-containing "a _b_ c", input-ah + var in/eax: (addr buffered-file) <- lookup input-storage + # output screen + var pg: paginated-screen + var pg-addr/ecx: (addr paginated-screen) <- address pg + initialize-fake-paginated-screen pg-addr, 8/rows, 6/cols, 5/page-width, 1/top-margin, 1/left-margin + # + render pg-addr, in + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen, 2, " a b c", "F - test-render-pseudoitalic-text/text" + check-screen-row-in-bold screen, 2, " b ", "F - test-render-pseudoitalic-text/bold" +} + +fn test-render-asterisk-in-text { + # input text + var input-storage: (handle buffered-file) + var input-ah/eax: (addr handle buffered-file) <- address input-storage + populate-buffered-file-containing "a*b*c", input-ah + var in/eax: (addr buffered-file) <- lookup input-storage + # output screen + var pg: paginated-screen + var pg-addr/ecx: (addr paginated-screen) <- address pg + initialize-fake-paginated-screen pg-addr, 8/nrows, 6/cols, 5/page-width, 1/top-margin, 1/left-margin + # + render pg-addr, in + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen, 2, " a*b*c", "F - test-render-bold-text/text" + check-screen-row-in-bold screen, 2, " ", "F - test-render-bold-text/bold" +} + +fn render-normal screen: (addr paginated-screen), fs: (addr buffered-file) { + var newline-seen?/esi: boolean <- copy 0/false + var start-of-paragraph?/edi: boolean <- copy 1/true + var previous-grapheme/ebx: grapheme <- copy 0 +$render-normal:loop: { + # if done-drawing?(screen) break + var done?/eax: boolean <- done-drawing? screen + compare done?, 0/false + break-if-!= + var c/eax: grapheme <- read-grapheme-buffered fs +$render-normal:loop-body: { + # if (c == EOF) break + compare c, 0xffffffff/end-of-file + break-if-= $render-normal:loop + + ## if (c == newline) perform some fairly sophisticated parsing for soft newlines + compare c, 0xa/newline + { + break-if-!= + # if it's the first newline, buffer it + compare newline-seen?, 0 + { + break-if-!= + newline-seen? <- copy 1/true + break $render-normal:loop-body + } + # otherwise render two newlines + { + break-if-= + add-grapheme screen, 0xa/newline + add-grapheme screen, 0xa/newline + newline-seen? <- copy 0/false + start-of-paragraph? <- copy 1/true + break $render-normal:loop-body + } + } + # if start of paragraph and c == '#', switch to header + compare start-of-paragraph?, 0 + { + break-if-= + compare c, 0x23/'#' + { + break-if-!= + render-header-line screen, fs + newline-seen? <- copy 1/true + break $render-normal:loop-body + } + } + # c is not a newline + start-of-paragraph? <- copy 0/false + # if c is unprintable (particularly a '\r' CR), skip it + compare c, 0x20 + loop-if-< $render-normal:loop + # If there's a newline buffered and c is a space, print the buffered + # newline (hard newline). + # If there's a newline buffered and c is not a newline or space, print a + # space (soft newline). + compare newline-seen?, 0/false +$render-normal:flush-buffered-newline: { + break-if-= + newline-seen? <- copy 0/false + { + compare c, 0x20 + break-if-!= + add-grapheme screen, 0xa/newline + break $render-normal:flush-buffered-newline + } + add-grapheme screen, 0x20/space + # fall through to print c + } + ## end soft newline support + +$render-normal:whitespace-separated-regions: { + # if previous-grapheme wasn't whitespace, skip this block + { + compare previous-grapheme, 0x20/space + break-if-= + compare previous-grapheme, 0xa/newline + break-if-= + break $render-normal:whitespace-separated-regions + } + # if (c == '*') switch to bold + compare c, 0x2a/* + { + break-if-!= + start-color-on-paginated-screen screen, 0xec/fg=darkish-grey, 7/bg=white + start-bold-on-paginated-screen screen + render-until-asterisk screen, fs + normal-text screen + break $render-normal:loop-body + } + # if (c == '_') switch to bold + compare c, 0x5f/_ + { + break-if-!= + start-color-on-paginated-screen screen, 0xec/fg=darkish-grey, 7/bg=white + start-bold-on-paginated-screen screen + render-until-underscore screen, fs + normal-text screen + break $render-normal:loop-body + } + } + # + add-grapheme screen, c + } # $render-normal:loop-body + previous-grapheme <- copy c + loop + } # $render-normal:loop +} + +fn render-header-line screen: (addr paginated-screen), fs: (addr buffered-file) { +$render-header-line:body: { + # compute color based on number of '#'s + var header-level/esi: int <- copy 1 # caller already grabbed one + var c/eax: grapheme <- copy 0 + { + # if done-drawing?(screen) return + { + var done?/eax: boolean <- done-drawing? screen + compare done?, 0/false + break-if-!= $render-header-line:body + } + # + c <- read-grapheme-buffered fs + # if (c != '#') break + compare c, 0x23/'#' + break-if-!= + # + header-level <- increment + # + loop + } + start-heading screen, header-level + { + # if done-drawing?(screen) break + { + var done?/eax: boolean <- done-drawing? screen + compare done?, 0/false + break-if-!= + } + # + c <- read-grapheme-buffered fs + # if (c == EOF) break + compare c, 0xffffffff/end-of-file + break-if-= + # if (c == newline) break + compare c, 0xa/newline + break-if-= + # + add-grapheme screen, c + # + loop + } + normal-text screen +} +} + +# colors for a light background, going from bright to dark (meeting up with bold-text) +fn start-heading screen: (addr paginated-screen), header-level: int { +$start-heading:body: { + start-bold-on-paginated-screen screen + compare header-level, 1 + { + break-if-!= + start-color-on-paginated-screen screen, 0xa0, 7 + break $start-heading:body + } + compare header-level, 2 + { + break-if-!= + start-color-on-paginated-screen screen, 0x7c, 7 + break $start-heading:body + } + compare header-level, 3 + { + break-if-!= + start-color-on-paginated-screen screen, 0x58, 7 + break $start-heading:body + } + compare header-level, 4 + { + break-if-!= + start-color-on-paginated-screen screen, 0x34, 7 + break $start-heading:body + } + start-color-on-paginated-screen screen, 0xe8, 7 +} +} + +fn render-until-asterisk screen: (addr paginated-screen), fs: (addr buffered-file) { + { + # if done-drawing?(screen) break + var done?/eax: boolean <- done-drawing? screen + compare done?, 0/false + break-if-!= + # + var c/eax: grapheme <- read-grapheme-buffered fs + # if (c == EOF) break + compare c, 0xffffffff/end-of-file + break-if-= + # if (c == '*') break + compare c, 0x2a/'*' + break-if-= + # + add-grapheme screen, c + # + loop + } +} + +fn render-until-underscore screen: (addr paginated-screen), fs: (addr buffered-file) { + { + # if done-drawing?(screen) break + var done?/eax: boolean <- done-drawing? screen + compare done?, 0/false + break-if-!= + # + var c/eax: grapheme <- read-grapheme-buffered fs + # if (c == EOF) break + compare c, 0xffffffff/end-of-file + break-if-= + # if (c == '_') break + compare c, 0x5f/'_' + break-if-= + # + add-grapheme screen, c + # + loop + } +} + +fn normal-text screen: (addr paginated-screen) { + reset-formatting-on-paginated-screen screen + start-color-on-paginated-screen screen, 0xec/fg=darkish-grey, 7/bg=white +} diff --git a/linux/browse/paginated-screen.mu b/linux/browse/paginated-screen.mu new file mode 100644 index 00000000..f4579d95 --- /dev/null +++ b/linux/browse/paginated-screen.mu @@ -0,0 +1,661 @@ +# If a screen is too wide, split it up into a fixed size of pages. +# We take control of drawing and moving the cursor, and delegate everything else. +# Never scroll; use the 'done-drawing?' method instead. +# +# Example usage: +# initialize-paginated-screen +# on each frame +# start-drawing +# while !done-drawing +# add-grapheme ... + +type paginated-screen { + screen: (handle screen) + nrows: int # const + ncols: int # const + page-width: int + top-margin: int + left-margin: int + # page bounds + toprow: int + botrow: int # (inclusive) + leftcol: int + rightcol: int # (exclusive) + # current cursor position + row: int + col: int +} + +fn initialize-paginated-screen _self: (addr paginated-screen), page-width: int, top-margin: int, left-margin: int { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var _screen-addr/eax: (addr screen) <- lookup *screen-ah + var screen-addr/edi: (addr screen) <- copy _screen-addr + var nrows/eax: int <- copy 0 + var ncols/ecx: int <- copy 0 + nrows, ncols <- screen-size screen-addr + var dest/edx: (addr int) <- copy 0 + # self->nrows = nrows + dest <- get self, nrows + copy-to *dest, nrows + # self->ncols = ncols + dest <- get self, ncols + copy-to *dest, ncols + # self->page-width = page-width + { + var tmp/eax: int <- copy page-width + dest <- get self, page-width + copy-to *dest, tmp + } + # self->top-margin = top-margin + { + var tmp/eax: int <- copy top-margin + dest <- get self, top-margin + copy-to *dest, tmp + } + # self->left-margin = left-margin + { + var tmp/eax: int <- copy left-margin + dest <- get self, left-margin + copy-to *dest, tmp + } + # self->toprow = 1 + top-margin + { + var tmp/eax: int <- copy top-margin + dest <- get self, toprow + copy-to *dest, 1 + add-to *dest, tmp + } + # self->botrow = nrows + { + dest <- get self, botrow + copy-to *dest, nrows + } + # + start-drawing self +} + +fn start-drawing _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + clear-paginated-screen self + var tmp/eax: (addr int) <- copy 0 + var tmp2/ecx: int <- copy 0 + # self->leftcol = 1 + left-margin + tmp <- get self, left-margin + tmp2 <- copy *tmp + tmp <- get self, leftcol + copy-to *tmp, 1 + add-to *tmp, tmp2 +#? print-string-to-real-screen "start: left column: " +#? print-int32-hex-to-real-screen *tmp + # self->rightcol = min(ncols+1, self->leftcol + page-width) + # . tmp2 = self->leftcol + page-width + tmp <- get self, page-width + tmp2 <- copy *tmp + tmp <- get self, leftcol + tmp2 <- add *tmp + # . if (tmp2 > ncols+1) tmp2 = ncols+1 + { + tmp <- get self, ncols + compare tmp2, *tmp + break-if-<= + tmp2 <- copy *tmp + tmp2 <- increment + } + # . self->rightcol = tmp2 + tmp <- get self, rightcol + copy-to *tmp, tmp2 +#? print-string-to-real-screen "; right column: " +#? print-int32-hex-to-real-screen *tmp +#? print-string-to-real-screen "\n" + # self->row = self->toprow + tmp <- get self, toprow + tmp2 <- copy *tmp + tmp <- get self, row + copy-to *tmp, tmp2 + # self->col = self->leftcol + tmp <- get self, leftcol + tmp2 <- copy *tmp + tmp <- get self, col + copy-to *tmp, tmp2 + # + reposition-cursor self +} + +fn done-drawing? _self: (addr paginated-screen) -> _/eax: boolean { + # if (self->leftcol == left-margin + 1) return false + var self/esi: (addr paginated-screen) <- copy _self + var tmp/eax: (addr int) <- get self, left-margin + var first-col/ecx: int <- copy *tmp + first-col <- increment + tmp <- get self, leftcol + $done-drawing:first-page?: { + compare first-col, *tmp + break-if-!= + return 0/false + } + # return self->rightcol > self->ncols + 1 + tmp <- get self, ncols + var max/ecx: int <- copy *tmp + max <- increment + tmp <- get self, rightcol +#? print-string-to-real-screen "done-drawing? " +#? print-int32-hex-to-real-screen *tmp +#? print-string-to-real-screen " vs " +#? print-int32-hex-to-real-screen max +#? print-string-to-real-screen "\n" + compare *tmp, max + { + break-if-> + return 0/false + } + return 1/true +} + +fn add-grapheme _self: (addr paginated-screen), c: grapheme { +#? print-string-to-real-screen "add-grapheme: " +#? print-grapheme-to-real-screen c +#? print-string-to-real-screen "\n" +$add-grapheme:body: { + var self/esi: (addr paginated-screen) <- copy _self + { + compare c, 0xa/newline + break-if-!= + next-line self + reposition-cursor self + break $add-grapheme:body + } + # print c + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + print-grapheme screen-addr, c + # self->col++ + var tmp/eax: (addr int) <- get self, col + increment *tmp + # if (self->col > self->rightcol) next-line(self) + var tmp2/ecx: int <- copy *tmp + tmp <- get self, rightcol + compare tmp2, *tmp + { + break-if-< + next-line self + reposition-cursor self + } +} +} + +## tests + +fn test-print-grapheme-on-paginated-screen { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 3/rows, 0xa/cols, 0xa/page-width, 0, 0 + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-grapheme-on-paginated-screen/done" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, "a", "F - test-print-grapheme-on-paginated-screen" +} + +fn test-print-single-page { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 2/rows, 4/cols, 2/page-width, 0, 0 + start-drawing pg + # pages at columns [1, 3), [3, 5) + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page/done-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page/done-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page/done-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page/done-4" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, "ab ", "F - test-print-single-page/row1" + check-screen-row screen-addr, 2, "cd ", "F - test-print-single-page/row2" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn test-print-single-page-narrower-than-page-width { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 2/rows, 4/cols, 5/page-width, 0, 0 + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width/done-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width/done-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width/done-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width/done-4" + } + { + var c/ecx: grapheme <- copy 0x65/e + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width/done-5" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, "abcd", "F - test-print-single-page-narrower-than-page-width/row1" + check-screen-row screen-addr, 2, "e ", "F - test-print-single-page-narrower-than-page-width/row2" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn test-print-single-page-narrower-than-page-width-with-margin { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 2/rows, 4/cols, 5/page-width, 0/top-margin, 1/left-margin + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width-with-margin/done-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width-with-margin/done-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width-with-margin/done-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width-with-margin/done-4" + } + { + var c/ecx: grapheme <- copy 0x65/e + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-single-page-narrower-than-page-width-with-margin/done-5" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, " abc", "F - test-print-single-page-narrower-than-page-width-with-margin/row1" + check-screen-row screen-addr, 2, " de ", "F - test-print-single-page-narrower-than-page-width-with-margin/row2" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn test-print-multiple-pages { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 2/rows, 2/cols, 1/page-width, 0, 0 + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages/done-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages/done-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages/done-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 1, "F - test-print-multiple-pages/done-4" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, "ac", "F - test-print-multiple-pages/row1" + check-screen-row screen-addr, 2, "bd", "F - test-print-multiple-pages/row2" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn test-print-multiple-pages-2 { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 2/rows, 4/cols, 2/page-width, 0, 0 + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-4" + } + { + var c/ecx: grapheme <- copy 0x65/e + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-5" + } + { + var c/ecx: grapheme <- copy 0x66/f + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-6" + } + { + var c/ecx: grapheme <- copy 0x67/g + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-2/done-7" + } + { + var c/ecx: grapheme <- copy 0x68/h + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 1, "F - test-print-multiple-pages-2/done-8" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, "abef", "F - test-print-multiple-pages-2/row1" + check-screen-row screen-addr, 2, "cdgh", "F - test-print-multiple-pages-2/row2" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn test-print-multiple-pages-with-margins { + var pg-on-stack: paginated-screen + var pg/eax: (addr paginated-screen) <- address pg-on-stack + initialize-fake-paginated-screen pg, 3/rows, 6/cols, 2/page-width, 1/top-margin, 1/left-margin + start-drawing pg + { + var c/ecx: grapheme <- copy 0x61/a + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-1" + } + { + var c/ecx: grapheme <- copy 0x62/b + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-2" + } + { + var c/ecx: grapheme <- copy 0x63/c + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-3" + } + { + var c/ecx: grapheme <- copy 0x64/d + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-4" + } + { + var c/ecx: grapheme <- copy 0x65/e + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-5" + } + { + var c/ecx: grapheme <- copy 0x66/f + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-6" + } + { + var c/ecx: grapheme <- copy 0x67/g + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 0, "F - test-print-multiple-pages-with-margins/grapheme-7" + } + { + var c/ecx: grapheme <- copy 0x68/h + add-grapheme pg, c + var done?/eax: boolean <- done-drawing? pg + var done/eax: int <- copy done? + check-ints-equal done, 1, "F - test-print-multiple-pages-with-margins/grapheme-8" + } + var screen-ah/eax: (addr handle screen) <- get pg, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + check-screen-row screen-addr, 1, " ", "F - test-print-multiple-pages-with-margins/row1" + check-screen-row screen-addr, 2, " ab ef", "F - test-print-multiple-pages-with-margins/row2" + check-screen-row screen-addr, 3, " cd gh", "F - test-print-multiple-pages-with-margins/row3" + # currently it's hard-coded that we avoid printing to the bottom-most row of the screen +} + +fn initialize-fake-paginated-screen _self: (addr paginated-screen), nrows: int, ncols: int, page-width: int, top-margin: int, left-margin: int { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + allocate screen-ah + var screen-addr/eax: (addr screen) <- lookup *screen-ah + initialize-screen screen-addr, nrows, ncols + initialize-paginated-screen self, page-width, top-margin, left-margin +} + +## simple delegates + +fn reposition-cursor _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var r/ecx: (addr int) <- get self, row + var c/edx: (addr int) <- get self, col +#? print-string-to-real-screen "reposition cursor: " +#? print-int32-hex-to-real-screen *r +#? print-string-to-real-screen ", " +#? print-int32-hex-to-real-screen *c +#? print-string-to-real-screen "\n" + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + move-cursor screen-addr, *r *c +} + +fn clear-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + clear-screen screen-addr +} + +fn start-color-on-paginated-screen _self: (addr paginated-screen), fg: int, bg: int { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + start-color screen-addr, fg, bg +} + +fn start-bold-on-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + start-bold screen-addr +} + +fn start-underline-on-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + start-underline screen-addr +} + +fn start-reverse-video-on-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + start-reverse-video screen-addr +} + +fn start-blinking-on-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + start-blinking screen-addr +} + +fn reset-formatting-on-paginated-screen _self: (addr paginated-screen) { + var self/esi: (addr paginated-screen) <- copy _self + var screen-ah/eax: (addr handle screen) <- get self, screen + var screen-addr/eax: (addr screen) <- lookup *screen-ah + reset-formatting screen-addr +} + +## helpers + +fn next-line _self: (addr paginated-screen) { +#? print-string-to-real-screen "next-line\n" + var self/esi: (addr paginated-screen) <- copy _self + var tmp/eax: (addr int) <- copy 0 + var tmp2/ecx: int <- copy 0 + # self->col = self->leftcol + tmp <- get self, leftcol + tmp2 <- copy *tmp + tmp <- get self, col + copy-to *tmp, tmp2 + # self->row++ + tmp <- get self, row + increment *tmp +#? print-string-to-real-screen "next-line: row: " +#? print-int32-hex-to-real-screen *tmp +#? print-string-to-real-screen "\n" + # if (self->row > self->botrow) next-page(self) + tmp2 <- copy *tmp + tmp <- get self, botrow + compare tmp2, *tmp + { + break-if-<= + next-page self + } +} + +fn next-page _self: (addr paginated-screen) { +#? print-string-to-real-screen "next-page\n" + var self/esi: (addr paginated-screen) <- copy _self + var tmp/eax: (addr int) <- copy 0 + var tmp2/ecx: int <- copy 0 +#? # temporary: stop +#? tmp <- get self, ncols +#? tmp2 <- copy *tmp +#? tmp <- get self, rightcol +#? copy-to *tmp, tmp2 + # real: multiple pages + # self->leftcol = self->rightcol + left-margin + tmp <- get self, rightcol + tmp2 <- copy *tmp + tmp <- get self, left-margin + tmp2 <- add *tmp + tmp <- get self, leftcol + copy-to *tmp, tmp2 +#? print-string-to-real-screen "left: " +#? print-int32-hex-to-real-screen tmp2 +#? print-string-to-real-screen "\n" + # self->rightcol = self->leftcol + page-width + tmp <- get self, page-width + tmp2 <- copy *tmp + tmp <- get self, leftcol + tmp2 <- add *tmp + tmp <- get self, rightcol + copy-to *tmp, tmp2 +#? print-string-to-real-screen "right: " +#? print-int32-hex-to-real-screen tmp2 +#? print-string-to-real-screen "\n" + # self->row = self->toprow + tmp <- get self, toprow + tmp2 <- copy *tmp + tmp <- get self, row + copy-to *tmp, tmp2 + # self->col = self->leftcol + tmp <- get self, leftcol + tmp2 <- copy *tmp + tmp <- get self, col + copy-to *tmp, tmp2 +} diff --git a/linux/browse/vimrc.vim b/linux/browse/vimrc.vim new file mode 100644 index 00000000..348fe364 --- /dev/null +++ b/linux/browse/vimrc.vim @@ -0,0 +1,2 @@ +" when opening files in this directory, load vimrc from cwd (top-level) +source vimrc.vim |