\ Bing chat session:

\ Constants
80 constant width
25 constant height
width height * constant size

( These constants are irrelevant to my own setup )

create canvas size cells allot
variable pen-x
variable pen-y
variable error-flag

( I dislike how variable is used instead of value. That mostly increases the error rate. )

\ Helpers
: index ( x y -- addr ) \ Convert (x,y) to memory address
  width * + cells canvas + ;

( OK, simple enough. I'm not using cells though! )

: in-bounds-BAD? ( x y -- flag )
  2dup 0 >= swap 0 >= swap
  2dup width < swap height < and and ;

( 2dup - pushes the top cell on the stack if it is non-zero? hmm. it looks like the doc is wrong. this is OVER OVER! )
( the algorithm when expanded copies the two cells at top, does a test is >= 0, swaps, does another test is >=0,
  swaps, copies the two cells for the second set of tests... wait a minute.
  ok, let's run this code word by word. 

  And...it's bogus! The second 2dup failed at something important.
)

: in-bounds-slow? ( x y -- t )
  2dup 0 >= swap 0 >= and -rot height < swap width < and and 
;

( this one is fixed. AND is quite slow in 24-bit though. )

: in-bounds-fast? ( x y -- t )
  2dup 0 >= swap 0 >= + -rot height < swap width < + + -4 =
;

( i think this one is faster and i've verified that it checks out. )


: set-error ( -- ) true error-flag ! ;
: clear-error ( -- ) false error-flag ! ;

( good enough, but i would just use VALUE and TO for this flag. )

: draw-point ( x y -- )
  2dup in-bounds?
  if index 1 swap ! clear-error
  else set-error drop drop
  then ;

( "if index 1" ???? )
( this is the start of the real routine but it needs the height/width computation )

0 value draw-success
: draw-point ( x y -- )
  2dup in-bounds? dup to draw-success
  if ." draw the x y!" drop drop
  else ." don't draw!" drop drop then
;



\ dup to draw-success
\ if width * + array-index + !
\ else drop drop then;

\ Pen movement
: move-to ( x y -- )
  2dup in-bounds?
  if pen-x ! pen-y ! clear-error
  else set-error drop drop
  then ;

: pen@ ( -- x y ) pen-x @ pen-y @ ;

\ Iterate over all points
: each-point ( xt -- )
  \ xt: execution token of ( x y -- )
  height 0 do
    width 0 do
      j i 2dup rot execute
    loop
  loop ;

\ Bresenham's line drawing
: ans ( n -- n ) dup 0< if negate then ;
: sgn ( n -- s ) dup 0> if 1 else dup 0< if -1 else 0 then then ;

: draw-line ( x0 y0 x1 y1 -- )
  >r >r >r >r     \ save x1 y1 x0 y1 on return stack
  r@ r@ - abs >r  \ dx
  r@ r@ - abs >r  \ dy
  r> r>           \ dy dx
  r@ r@ - sgn >r  \ sy
  r@ r@ - sgn >r  \ sx
  r> r> r> r> \ x0 y0 x1 y1
  2dup draw-point
  begin
    2dup <> or
  while
    over over - abs over over - abs > if
      over over - sgn pen-x @ + pen-x !
    else
      over over - sgn pen-y @ + pen-y !
    then
    pen@ draw-point
  repeat
  2drop 2drop ;

\ Example usage
: .xy ( x y -- ) ." (" . ." , " . ." ) "

: examples
  \ Move pen to  (10, 5)
  10 5 move-to
  
  \ Draw a line from (10, 5) to (30, 20)
  10 5 30 20 draw-line

  \ Iterate over all points and print coordinates
  ' .xy each-point
;

\ Notes
\ You can customize the drawing value (currently 1)
\ or extend the canvas to support colors or layers.

\ The draw-line uses a simplified version of Bresenham's algorithm for clarity,
\ it can be optimized further.

\ Error handling is minimal - error-flag is set when an operation goes out of bounds.

