drawParagraph :: Context -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> IO ()
drawParagraph c x y w h mx my =
  do save c
     fontSize c 18
     fontFace c "sans"
     textAlign c (S.fromList [AlignLeft,AlignTop])
     (_,_,lineh) <- textMetrics c
     gutter <- newIORef Nothing
     yEnd <- newIORef y
     NVG.textBreakLines c text w 3 $ \row i -> do
       let y' = y + fromIntegral i * lineh
           hit = mx > x && mx < (x+w) && my >= y' && my < (y' + lineh)
       writeIORef yEnd y'
       beginPath c
       fillColor c (rgba 255 255 255 (if hit then 64 else 16))
       rect c x y' (width row) lineh
       fill c

       fillColor c (rgba 255 255 255 255)
       Internal.text c x y' (start row) (end row)
       when hit $ do
         let caretxInit = if mx < x+ (width row) / 2 then x else x + width row
             ps = x
         glyphs <- NVG.textGlyphPositions c x y (start row) (end row) 100
         let leftBorders = V.map glyphX glyphs
             rightBorders = V.snoc (V.drop 1 leftBorders) (x + width row)
             rightPoints = V.zipWith (\x y -> 0.3*x+0.7*y) leftBorders rightBorders
             leftPoints = V.cons x (V.take (V.length glyphs - 1) rightPoints)
             caretx = maybe caretxInit (glyphX . (glyphs V.!)) $ V.findIndex (\(px,gx) -> mx >= px && mx < gx) $ V.zip leftPoints rightPoints
         beginPath c
         fillColor c (rgba 255 192 0 255)
         rect c caretx y' 1 lineh
         fill c
         -- realized too late that I probably should have used a fold
         writeIORef gutter (Just (i+1,x-10,y'+lineh/2))
     gutter' <- readIORef gutter
     forM_ gutter' $ \(gutter,gx,gy) -> do
       let txt = T.pack $ show gutter
       fontSize c 13
       textAlign c (S.fromList [AlignRight,AlignMiddle])
       (Bounds (V4 b0 b1 b2 b3)) <- textBounds c gx gy txt
       beginPath c
       fillColor c (rgba 255 192 0 255)
       roundedRect c (b0-4) (b1-2) ((b2-b0)+8) ((b3-b1)+4) (((b3-b1)+4)/2-1)
       fill c
       fillColor c (rgba 32 32 32 255)
       NVG.text c gx gy txt

     y' <- (\x -> x+20+lineh) <$> readIORef yEnd

     fontSize c 13
     textAlign c (S.fromList [AlignLeft, AlignTop])
     textLineHeight c 1.2

     (Bounds (V4 b0 b1 b2 b3)) <- textBoxBounds c x y' 150 helpText

     let gx = abs $ (mx - (b0+b2)*0.5) / (b0 - b2)
         gy = abs $ (my - (b1+b3)*0.5) / (b1 - b3)
         a = (\x -> clamp x 0 1) $ max gx gy - 0.5
     globalAlpha c a

     beginPath c
     fillColor c (rgba 220 220 220 255)
     roundedRect c (b0-2) (b1-2) ((b2-b0)+4) ((b3-b1)+4) 3
     let px = (b2+b0)/2
     moveTo c px (b1-10)
     lineTo c (px+7) (b1+1)
     lineTo c (px-7) (b1+1)
     fill c

     fillColor c (rgba 0 0 0 220)
     textBox c x y' 150 helpText
         
     restore c
  where text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she    was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."
        helpText = "Hover your mouse over the text to see calculated caret position."
drawParagraph :: Context -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> CFloat -> IO ()
drawParagraph c x y w h mx my =
  do save c
     fontSize c 18
     fontFace c "sans"
     textAlign c (S.fromList [AlignLeft,AlignTop])
     (_,_,lineh) <- textMetrics c
     gutter <- newIORef Nothing
     yEnd <- newIORef y
     NVG.textBreakLines c text w 3 $ \row i -> do
       let y' = y + fromIntegral i * lineh
           hit = mx > x && mx < (x+w) && my >= y' && my < (y' + lineh)
       writeIORef yEnd y'
       beginPath c
       fillColor c (rgba 255 255 255 (if hit then 64 else 16))
       rect c x y' (width row) lineh
       fill c

       fillColor c (rgba 255 255 255 255)
       Internal.text c x y' (start row) (end row)
       when hit $ do
         let caretxInit = if mx < x+ (width row) / 2 then x else x + width row
             ps = x
         glyphs <- NVG.textGlyphPositions c x y (start row) (end row) 100
         let leftBorders = V.map glyphX glyphs
             rightBorders = V.snoc (V.drop 1 leftBorders) (x + width row)
             rightPoints = V.zipWith (\x y -> 0.3*x+0.7*y) leftBorders rightBorders
             leftPoints = V.cons x (V.take (V.length glyphs - 1) rightPoints)
             caretx = maybe caretxInit (glyphX . (glyphs V.!)) $ V.findIndex (\(px,gx) -> mx >= px && mx < gx) $ V.zip leftPoints rightPoints
         beginPath c
         fillColor c (rgba 255 192 0 255)
         rect c caretx y' 1 lineh
         fill c
         -- realized too late that I probably should have used a fold
         writeIORef gutter (Just (i+1,x-10,y'+lineh/2))
     gutter' <- readIORef gutter
     forM_ gutter' $ \(gutter,gx,gy) -> do
       let txt = T.pack $ show gutter
       fontSize c 13
       textAlign c (S.fromList [AlignRight,AlignMiddle])
       (Bounds (V4 b0 b1 b2 b3)) <- textBounds c gx gy txt
       beginPath c
       fillColor c (rgba 255 192 0 255)
       roundedRect c (b0-4) (b1-2) ((b2-b0)+8) ((b3-b1)+4) (((b3-b1)+4)/2-1)
       fill c
       fillColor c (rgba 32 32 32 255)
       NVG.text c gx gy txt

     y' <- (\x -> x+20+lineh) <$> readIORef yEnd

     fontSize c 13
     textAlign c (S.fromList [AlignLeft, AlignTop])
     textLineHeight c 1.2

     (Bounds (V4 b0 b1 b2 b3)) <- textBoxBounds c x y' 150 helpText

     let gx = abs $ (mx - (b0+b2)*0.5) / (b0 - b2)
         gy = abs $ (my - (b1+b3)*0.5) / (b1 - b3)
         a = (\x -> clamp x 0 1) $ max gx gy - 0.5
     globalAlpha c a

     beginPath c
     fillColor c (rgba 220 220 220 255)
     roundedRect c (b0-2) (b1-2) ((b2-b0)+4) ((b3-b1)+4) 3
     let px = (b2+b0)/2
     moveTo c px (b1-10)
     lineTo c (px+7) (b1+1)
     lineTo c (px-7) (b1+1)
     fill c

     fillColor c (rgba 0 0 0 220)
     textBox c x y' 150 helpText
         
     restore c
  where text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she    was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."
        helpText = "Hover your mouse over the text to see calculated caret position."
drawParagraph c x y w h mx my =
  do save c
     fontSize c 18
     fontFace c "sans"
     textAlign c (S.fromList [AlignLeft,AlignTop])
     (_,_,lineh) <- textMetrics c
     gutter <- newIORef Nothing
     yEnd <- newIORef y
     NVG.textBreakLines c text w 3 $ \row i -> do
       let y' = y + fromIntegral i * lineh
           hit = mx > x && mx < (x+w) && my >= y' && my < (y' + lineh)
       writeIORef yEnd y'
       beginPath c
       fillColor c (rgba 255 255 255 (if hit then 64 else 16))
       rect c x y' (width row) lineh
       fill c

       fillColor c (rgba 255 255 255 255)
       Internal.text c x y' (start row) (end row)
       when hit $ do
         let caretxInit = if mx < x+ (width row) / 2 then x else x + width row
             ps = x
         glyphs <- NVG.textGlyphPositions c x y (start row) (end row) 100
         let leftBorders = V.map glyphX glyphs
             rightBorders = V.snoc (V.drop 1 leftBorders) (x + width row)
             rightPoints = V.zipWith (\x y -> 0.3*x+0.7*y) leftBorders rightBorders
             leftPoints = V.cons x (V.take (V.length glyphs - 1) rightPoints)
             caretx = maybe caretxInit (glyphX . (glyphs V.!)) $ V.findIndex (\(px,gx) -> mx >= px && mx < gx) $ V.zip leftPoints rightPoints
         beginPath c
         fillColor c (rgba 255 192 0 255)
         rect c caretx y' 1 lineh
         fill c
         -- realized too late that I probably should have used a fold
         writeIORef gutter (Just (i+1,x-10,y'+lineh/2))
     gutter' <- readIORef gutter
     forM_ gutter' $ \(gutter,gx,gy) -> do
       let txt = T.pack $ show gutter
       fontSize c 13
       textAlign c (S.fromList [AlignRight,AlignMiddle])
       (Bounds (V4 b0 b1 b2 b3)) <- textBounds c gx gy txt
       beginPath c
       fillColor c (rgba 255 192 0 255)
       roundedRect c (b0-4) (b1-2) ((b2-b0)+8) ((b3-b1)+4) (((b3-b1)+4)/2-1)
       fill c
       fillColor c (rgba 32 32 32 255)
       NVG.text c gx gy txt

     y' <- (\x -> x+20+lineh) <$> readIORef yEnd

     fontSize c 13
     textAlign c (S.fromList [AlignLeft, AlignTop])
     textLineHeight c 1.2

     (Bounds (V4 b0 b1 b2 b3)) <- textBoxBounds c x y' 150 helpText

     let gx = abs $ (mx - (b0+b2)*0.5) / (b0 - b2)
         gy = abs $ (my - (b1+b3)*0.5) / (b1 - b3)
         a = (\x -> clamp x 0 1) $ max gx gy - 0.5
     globalAlpha c a

     beginPath c
     fillColor c (rgba 220 220 220 255)
     roundedRect c (b0-2) (b1-2) ((b2-b0)+4) ((b3-b1)+4) 3
     let px = (b2+b0)/2
     moveTo c px (b1-10)
     lineTo c (px+7) (b1+1)
     lineTo c (px-7) (b1+1)
     fill c

     fillColor c (rgba 0 0 0 220)
     textBox c x y' 150 helpText
         
     restore c
  where text = "This is longer chunk of text.\n \n Would have used lorem ipsum but she    was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."
        helpText = "Hover your mouse over the text to see calculated caret position."