require 'keychord' require 'button' local utf8 = require 'utf8' -- lines is an array of lines -- a line is either: -- a string containing text -- or a drawing -- a drawing is a table with: -- a (y) coord in pixels, -- a (h)eight, -- an array of points, and -- an array of shapes -- a shape is a table containing: -- a mode -- an array points for mode 'freehand' (raw x,y coords; freehand drawings don't pollute the points array of a drawing) -- an array vertices for mode 'polygon', 'rectangle', 'square' -- p1, p2 for mode 'line' -- p1, p2, arrow-mode for mode 'arrow-line' -- center, radius for mode 'circle' -- center, radius, start_angle, end_angle for mode 'arc' -- Unless otherwise specified, coord fields are normalized; a drawing is always 256 units wide -- The field names are carefully chosen so that switching modes in midstream -- remembers previously entered points where that makes sense. -- -- Open question: how to maintain Sketchpad-style constraints? Answer for now: -- we don't. Constraints operate only for the duration of a drawing operation. -- We'll continue to persist them just to keep the option open to continue -- solving for them. But for now, this is a program to create static drawings -- once, and read them passively thereafter. lines = {''} cursor_line = 1 -- this is a line -- ^cursor_pos = 1 -- ^cursor_pos = 2 -- ... -- ^cursor_pos past end of line is 15 cursor_pos = #lines[cursor_line]+1 screenw, screenh, screenflags = 0, 0, nil current_mode = 'line' previous_mode = nil -- All drawings span 100% of some conceptual 'page width' and divide it up -- into 256 parts. `drawingw` describes their width in pixels. drawingw = nil -- pixels function pixels(n) -- parts to pixels return n*drawingw/256 end function coord(n) -- pixels to parts return math.floor(n*256/drawingw) end filename = 'lines.txt' function love.load(arg) -- maximize window love.window.setMode(0, 0) -- maximize screenw, screenh, screenflags = love.window.getMode() -- shrink slightly to account for window decoration screenw = screenw-100 screenh = screenh-100 love.window.setMode(screenw, screenh) love.window.setTitle('Text with Lines') drawingw = math.floor(screenh/2/40)*40 love.keyboard.setTextInput(true) -- bring up keyboard on touch screen if #arg > 0 then filename = arg[1] end lines = load_from_disk(filename) love.window.setTitle('Text with Lines - '..filename) end function love.filedropped(file) filename = file:getFilename() file:open('r') lines = load_from_file(file) file:close() love.window.setTitle('Text with Lines - '..filename) end function love.draw() button_handlers = {} love.graphics.setColor(1, 1, 1) love.graphics.rectangle('fill', 0, 0, screenw-1, screenh-1) love.graphics.setColor(0, 0, 0) local text = love.graphics.newText(love.graphics.getFont(), '') local y = 0 for i,line in ipairs(lines) do y = y+25 text = love.graphics.newText(love.graphics.getFont(), line) if line == '' then button('draw', {x=4,y=y+4, w=12,h=12, color={1,1,0}, icon = function(x,y) love.graphics.setColor(0.7,0.7,0.7) love.graphics.rectangle('line', x,y, 12,12) love.graphics.line(4,y+6, 16,y+6) love.graphics.line(10,y, 10,y+12) love.graphics.setColor(0, 0, 0) end, onpress1 = function() table.insert(lines, i, {y=y, h=256/2, points={}, shapes={}, pending={}}) end}) if i == cursor_line then love.graphics.setColor(0,0,0) love.graphics.print('_', 25, y+6) -- drop the cursor down a bit to account for the increased font size end elseif type(line) == 'table' then -- line drawing line.y = y y = y+pixels(line.h) local pmx,pmy = love.mouse.getX(), love.mouse.getY() if pmx > 16 and pmx < 16+drawingw and pmy > line.y and pmy < line.y+pixels(line.h) then love.graphics.setColor(0.75,0.75,0.75) love.graphics.rectangle('line',
const NimStackTrace = compileOption("stacktrace")
const NimStackTraceMsgs = compileOption("stacktraceMsgs")
template procName*(): string =
## returns current C/C++ function name
when defined(c) or defined(cpp):
var name {.inject, noinit.}: cstring
{.emit: "`name` = __func__;".}
$name
template getPFrame*(): PFrame =
## avoids a function call (unlike `getFrame()`)
block:
when NimStackTrace:
var framePtr {.inject, noinit.}: PFrame
{.emit: "`framePtr` = &FR_;".}
framePtr
template setFrameMsg*(msg: string, prefix = " ") =
## attach a msg to current `PFrame`. This can be called multiple times
## in a given PFrame. Noop unless passing --stacktraceMsgs and --stacktrace
when NimStackTrace and NimStackTraceMsgs:
block:
var fr {.inject, noinit.}: PFrame
{.emit: "`fr` = &FR_;".}
# consider setting a custom upper limit on size (analog to stack overflow)
frameMsgBuf.setLen fr.frameMsgLen
frameMsgBuf.add prefix
frameMsgBuf.add msg
fr.frameMsgLen += prefix.len + msg.len