1065 lines
37 KiB
VimL
1065 lines
37 KiB
VimL
|
" File: sketch.vim
|
|||
|
" Version: 0.3.2
|
|||
|
" Date: 2004-01-18
|
|||
|
" Author: Antony Scriven <ads@metawire.org>
|
|||
|
" Maintainer: Antony Scriven <ads@metawire.org>
|
|||
|
" Description: Line drawing, drag and drop, tables, arrows, boxes, fills,
|
|||
|
" using the mouse.
|
|||
|
"
|
|||
|
" Tutorial version: 2003-10-02
|
|||
|
"
|
|||
|
" Usage and settings
|
|||
|
" ------------------
|
|||
|
" See the file sketch.tut for a tutorial. There isn't a help file yet.
|
|||
|
"
|
|||
|
"
|
|||
|
" Change or uncomment this line so you can start or stop Sketch.
|
|||
|
" noremap <F1> :call ToggleSketch()<CR>
|
|||
|
"
|
|||
|
" Don't have a meta/alt key? Use this mapping to switch between square corners
|
|||
|
" and rounded corners for boxes/lines
|
|||
|
" nnoremap <buffer> <silent> <AnyKeyYouLike> <LeftMouse>:call NextCornerStyle()<CR>
|
|||
|
"
|
|||
|
" Release notes
|
|||
|
" -------------
|
|||
|
" 0.3.2 - Tabs still caused garbled screen when dragging transparent
|
|||
|
" objects. Fixed.
|
|||
|
" 0.3.1 - cursor() can cause problems in a file with tabs when using
|
|||
|
" virutal edit mode. Changed to use G and |. Many tutorial
|
|||
|
" errors fixed.
|
|||
|
" 0.3.0 - Flood fill with arbitrary character added.
|
|||
|
" 0.2.3 - Bug 6 fixed.
|
|||
|
" 0.2.2 - Error in the tutorial that I thought I'd fixed is now really
|
|||
|
" fixed. Thanks to pinkie..
|
|||
|
" - Tutorial updated.
|
|||
|
" 0.2.1 - Bug 9 fixed.
|
|||
|
" - Tutorial updated.
|
|||
|
" - Keys rearranged again, sorry. Most important are the line
|
|||
|
" drawing actions. These are all accessible via shift and
|
|||
|
" control keys. Meta is used for painting/fat erase. This
|
|||
|
" shouldn't be much of a loss if your terminal/keyboard
|
|||
|
" doesn't have or doesn't like the meta/alt key.
|
|||
|
" 0.2.0 - Bug 3 fixed.
|
|||
|
" - Bug 1 fixed.
|
|||
|
" - Bug 7 fixed.
|
|||
|
" - Bug 5 fixed.
|
|||
|
" - Corrected tutorial errors.
|
|||
|
" Thanks to Tijs Van Den Bogaard.
|
|||
|
" Added a quick reference card.
|
|||
|
" - Changed some commands around slightly after
|
|||
|
" encountering some usability problems:
|
|||
|
" Shift+LeftMouse is now paint.
|
|||
|
" Control+LeftMouse is brush select.
|
|||
|
" Shift+RightMouse is erase.
|
|||
|
" Control+RightMouse is fat erase.
|
|||
|
" - Vis select then line/box/fill sets the arrowhead.
|
|||
|
" - Drag/drop opaque & transparent.
|
|||
|
" - Lines/boxes can have round corners: <M-LeftMouse>
|
|||
|
" 0.1.1 Bug 2 fixed.
|
|||
|
" 0.1.0 Initial beta release
|
|||
|
"
|
|||
|
"
|
|||
|
" Please don't tell me my code is horrible, I know it is. It started as a
|
|||
|
" quick test and I've hacked on all sorts of features in a nasty nasty way.
|
|||
|
" Using virtualedit seems buggy, or at least how it works isn't entirely
|
|||
|
" obvious in certain situations. So I've hacked in some workarounds.
|
|||
|
" I'll tidy it up later (honest).
|
|||
|
"
|
|||
|
" To do, in order of priority (notes and examples at the end of the file)
|
|||
|
" -----------------------------------------------------------------------
|
|||
|
" - make a better behaved plugin
|
|||
|
" <SID> etc
|
|||
|
" uses registers in a few places withouth documenting this. Need a scheme to
|
|||
|
" avoid this.
|
|||
|
" - use the new setreg features if ver = vim6.2
|
|||
|
" - vim help file with command reference and link to tutorial
|
|||
|
" - Rewrite the code nicely :-)
|
|||
|
" >>Version 1
|
|||
|
" - diagonals
|
|||
|
" - coarser drawing to make straight lines and diagonals easier
|
|||
|
" - keyboard support
|
|||
|
" ...
|
|||
|
" - painting with colours! (horrendously slow last I checked)
|
|||
|
"
|
|||
|
" Known bugs
|
|||
|
" ----------
|
|||
|
" 10. Transparent drag doesn't quite work for dragging to column 1.
|
|||
|
" 4. Try drawing from below the bottom of the file. I don't think this is
|
|||
|
" fixable. But it may be possible to make it react a little more sanely.
|
|||
|
" 8. When dragging an object, doesn't quite work right when you are one
|
|||
|
" column to the right of your starting point.
|
|||
|
" Has this gone away?
|
|||
|
"
|
|||
|
" Fixed bugs
|
|||
|
" ----------
|
|||
|
" 9. If mousemodel=popup then rightrelease gives an annoying menu.
|
|||
|
" --Solution: save &mousemodel; let mousemodel=''
|
|||
|
" 5. Select a line, then left-click to draw it. Now if you
|
|||
|
" double-click the arrow is in the correct direction. However, if
|
|||
|
" you select a line, then double-click to draw a line+arrow, the
|
|||
|
" arrowhead is not in the correct direction.
|
|||
|
" -- Fixed by getting rightrelease to handle this.
|
|||
|
" 6. Right vertical line of a visual box is drawn one
|
|||
|
" column to the right. Happens if the last cursor position of the visual
|
|||
|
" selection is on an empty line, and is to the right of the starting
|
|||
|
" position.
|
|||
|
" 7. Drawing through, e.g., letters produces '+'s. This should be lines.
|
|||
|
" 3. Visual selection, then click in another window: the click is
|
|||
|
" interpreted with the buffer-local map of the window you are
|
|||
|
" drawing in and you get a lot of error messages. This should be
|
|||
|
" fixable. (However not for erase :-()
|
|||
|
" 1. filling a box: rarely the leftmost, uppermost `-' isn't drawn.
|
|||
|
" Hopefully fixed by fixing bug 2!
|
|||
|
" 2. very rarely the left vertical line of a visual box is drawn one
|
|||
|
" column to the right ?? (virtualedit problem or my strlen()
|
|||
|
" problem). Happens if the last cursor position of the visual
|
|||
|
" selection is on an empty line, and is to the right of the
|
|||
|
" starting position.
|
|||
|
"
|
|||
|
"
|
|||
|
" ----------------------------------------------------------------------
|
|||
|
" To follow: poorly named, poorly commented, poorly written functions in
|
|||
|
" a random order. Sorry.
|
|||
|
|
|||
|
fun! Cursor(line,col)
|
|||
|
exe 'silent norm! ' . a:line . 'G' . a:col . '|'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! ToggleSketch()
|
|||
|
if !exists("b:Sketch_loaded")
|
|||
|
let b:Sketch_loaded = 1
|
|||
|
call Sketch()
|
|||
|
echo '[Sketch on]'
|
|||
|
norm! zRz.
|
|||
|
else
|
|||
|
unlet b:Sketch_loaded
|
|||
|
call NoSketch()
|
|||
|
echo '[Sketch off]'
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! NextBrush()
|
|||
|
let b:brushes = strpart(b:brushes,1,strlen(b:brushes)-1).b:brushes[0]
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! NextCornerStyle()
|
|||
|
if b:roundcorners == 1
|
|||
|
let b:roundcorners = 0
|
|||
|
else
|
|||
|
let b:roundcorners = 1
|
|||
|
endif
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! MarkVisStart()
|
|||
|
call SketchSavePos('auto')
|
|||
|
let b:Vis_start_line = line(".")
|
|||
|
let b:Vis_start_col = virtcol(".")
|
|||
|
let g:Sketch_winnr = winnr()
|
|||
|
endfun
|
|||
|
|
|||
|
fun! MarkVisEnd()
|
|||
|
"Fixes bug 3. Clicking outside of the window where you first made the
|
|||
|
"selection.
|
|||
|
if winnr() != g:Sketch_winnr
|
|||
|
return 'abort'
|
|||
|
endif
|
|||
|
normal! gv
|
|||
|
let b:Vis_end_line = line(".")
|
|||
|
let b:Vis_end_col = virtcol(".")
|
|||
|
normal!
|
|||
|
return ''
|
|||
|
endfun
|
|||
|
|
|||
|
fun! Sketch()
|
|||
|
let b:brushes = '.:#'
|
|||
|
let b:Sketch_dir2 = 0
|
|||
|
let b:Sketch_dir = 'r'
|
|||
|
let b:Sketch_line = 0
|
|||
|
let b:Sketch_col = 0
|
|||
|
let b:Sketch_savedguiopts = &go
|
|||
|
let b:Sketch_savedmousemodel = &mousemodel
|
|||
|
set mousemodel=
|
|||
|
let b:Vis_start_line = 0
|
|||
|
let b:Vis_start_col = 0
|
|||
|
let b:Vis_end_line = 0
|
|||
|
let b:Vis_end_col = 0
|
|||
|
let b:Sketch_erasesize = 1
|
|||
|
let g:Sketch_winnr = winnr()
|
|||
|
let b:roundcorners = 0
|
|||
|
set go+=rb
|
|||
|
setl ve=all
|
|||
|
|
|||
|
|
|||
|
"Lines
|
|||
|
nnoremap <buffer> <silent> <LeftMouse> <LeftMouse>:call SketchClick('-')<CR>
|
|||
|
nnoremap <buffer> <silent> <LeftDrag> <LeftMouse>:call SketchDrag()<CR>
|
|||
|
|
|||
|
"Arrow
|
|||
|
nnoremap <buffer> <silent> <2-LeftMouse> :call SketchClick('>')<CR>
|
|||
|
"Single vert bar
|
|||
|
nnoremap <buffer> <silent> <3-LeftMouse> :call SketchClick('\|')<CR>
|
|||
|
|
|||
|
"Painting
|
|||
|
nnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:call SketchPaint()<CR>
|
|||
|
nnoremap <buffer> <silent> <C-LeftDrag> <LeftMouse>:call SketchPaint()<CR>
|
|||
|
nnoremap <buffer> <silent> <M-LeftMouse> <LeftMouse>:call NextBrush()<CR>
|
|||
|
nnoremap <buffer> <silent> <M-2-LeftMouse> <LeftMouse>:call NextBrush()<CR>
|
|||
|
nnoremap <buffer> <silent> <M-3-LeftMouse> <LeftMouse>:call NextBrush()<CR>
|
|||
|
nnoremap <buffer> <silent> <M-4-LeftMouse> <LeftMouse>:call NextBrush()<CR>
|
|||
|
|
|||
|
"Selection
|
|||
|
nnoremap <buffer> <silent> <RightMouse> <LeftMouse>:call MarkVisStart()<CR><4-LeftMouse>
|
|||
|
vnoremap <buffer> <silent> <RightDrag> <LeftDrag>
|
|||
|
vnoremap <buffer> <silent> <RightRelease> <LeftMouse>:call SketchSavePos('auto')<CR>gv
|
|||
|
"The gv"ap at the end prevents flicker when M-RightDrag does the undo.
|
|||
|
vnoremap <buffer> <silent> <S-RightMouse> <LeftMouse>:call VisSaveDims()<CR>gv"pygv"pp:let b:above = @p<CR>
|
|||
|
nnoremap <buffer> <silent> <S-RightDrag> u<LeftMouse>:call VisWithSavedDims()<CR>"pp
|
|||
|
nnoremap <buffer> <silent> <RightDrag> u<LeftMouse>:call VisWithSavedDims()<CR>:call PasteTransparent()<CR>:call VisWithSavedDims()<CR>"pp
|
|||
|
|
|||
|
"Erase
|
|||
|
nnoremap <buffer> <silent> <C-RightMouse> <LeftMouse>:call SketchErase('small')<CR>
|
|||
|
nnoremap <buffer> <silent> <C-RightDrag> <LeftMouse>:call SketchErase('small')<CR>
|
|||
|
nnoremap <buffer> <silent> <M-RightMouse> <LeftMouse>:call SketchErase('big')<CR>
|
|||
|
nnoremap <buffer> <silent> <M-RightDrag> <LeftMouse>:call SketchErase('big')<CR>
|
|||
|
vnoremap <buffer> <silent> <RightMouse> <LeftMouse>:call VisSaveDims()<CR>gv"pygv"pp:let b:above = @p<CR>gv:call SketchErase('vblock')<CR><LeftMouse>
|
|||
|
" vnoremap <buffer> <silent> <RightMouse> <LeftMouse>:call VisSaveDims()<CR>gv"py:let b:above = @p<CR>gv:call SketchErase('vblock')<CR><LeftMouse>
|
|||
|
vnoremap <buffer> <silent> <2-RightMouse> <LeftMouse>:call VisSaveDims()<CR>gv"pygv"pp:let b:above = @p<CR>gv:call SketchErase('vblock')<CR><LeftMouse>
|
|||
|
"vnoremap <buffer> <silent> <RightMouse> :call SketchErase('vblock')<CR><LeftMouse>
|
|||
|
|
|||
|
"Fill
|
|||
|
vnoremap <buffer> <silent> <LeftMouse> <LeftMouse>:call SketchFillBox('transparent')<CR>
|
|||
|
vnoremap <buffer> <silent> <S-LeftMouse> <LeftMouse>:call SketchFillBox('opaque')<CR>
|
|||
|
vnoremap <buffer> <silent> <C-LeftMouse> <LeftMouse>:call SketchFillBrush('opaque')<CR>
|
|||
|
nnoremap <buffer> <silent> <S-LeftMouse> <LeftMouse>:call NextCornerStyle()<CR>
|
|||
|
nnoremap <buffer> <silent> <S-2-LeftMouse> <LeftMouse>:call NextCornerStyle()<CR>
|
|||
|
nnoremap <buffer> <silent> <S-3-LeftMouse> <LeftMouse>:call NextCornerStyle()<CR>
|
|||
|
nnoremap <buffer> <silent> <S-4-LeftMouse> <LeftMouse>:call NextCornerStyle()<CR>
|
|||
|
nnoremap <buffer> <leader>f :call <SID>Fill()<CR>
|
|||
|
endfun
|
|||
|
|
|||
|
" Replace tabs in a:str with the correct number of spaces.
|
|||
|
" Need to supply the tabstop value and the offset from the left edge of the
|
|||
|
" screen.
|
|||
|
" This implements the fix for version 0.3.2.
|
|||
|
fun! s:EscapeAll(str)
|
|||
|
return escape(a:str, '\.*^$[]')
|
|||
|
endfun
|
|||
|
let s:spc = ' '
|
|||
|
fun! s:Detab(str, ts, offset)
|
|||
|
let i = 0
|
|||
|
let n = 0
|
|||
|
let str = a:str
|
|||
|
while 1
|
|||
|
let i = match(str, '\t\|\n', i)
|
|||
|
if i == -1 | break | endif
|
|||
|
if str[i] == "\n"
|
|||
|
let n = i + 1
|
|||
|
else
|
|||
|
let numspaces = a:ts - ((i - n + a:offset) % a:ts)
|
|||
|
let str = substitute(str, '\t', strpart(s:spc, 0, numspaces ), '')
|
|||
|
endif
|
|||
|
let i = i + 1
|
|||
|
endwhile
|
|||
|
return str
|
|||
|
endfun
|
|||
|
|
|||
|
fun! PasteTransparent() range
|
|||
|
normal! gv"oy
|
|||
|
let above = b:above
|
|||
|
"
|
|||
|
"s:Detab() has a noticeable impact on speed. So make sure there
|
|||
|
"really are tabs before removing them!
|
|||
|
if @o =~ '\t'
|
|||
|
let below = s:Detab(@o,&ts,virtcol('.')-1)
|
|||
|
else
|
|||
|
let below = @o
|
|||
|
endif
|
|||
|
|
|||
|
"Need this if..endif, because you can't write .\{0} in a regexp.
|
|||
|
if above[0] == ' '
|
|||
|
let above = substitute(above, ' ', escape(below[0],'&'), '')
|
|||
|
endif
|
|||
|
let i = 1
|
|||
|
while i < strlen(above)
|
|||
|
if above[i] == ' '
|
|||
|
let above = substitute(above, '\(.\{'.i.'}\).', '\1'.escape(below[i],'&'), '')
|
|||
|
endif
|
|||
|
let i = i + 1
|
|||
|
endwhile
|
|||
|
let @p = above
|
|||
|
"normal! ms
|
|||
|
let pos = SavePos(0)
|
|||
|
$ put p
|
|||
|
"Need the zero. If @p has leading spaces, cursor will be on first non-blank
|
|||
|
"of the line.
|
|||
|
normal! 0G$h"pydG
|
|||
|
exe pos
|
|||
|
endfun
|
|||
|
|
|||
|
fun! Move()
|
|||
|
if exists("b:vis_just_saved")
|
|||
|
"TRAILING SPACE
|
|||
|
normal! gvr
|
|||
|
let b:vis_just_saved = 0
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! VisSaveDims() range
|
|||
|
normal! gv
|
|||
|
if virtcol(".") > b:Vis_start_col
|
|||
|
let b:viswidth = virtcol(".") - b:Vis_start_col + 1
|
|||
|
else
|
|||
|
let b:viswidth = b:Vis_start_col - virtcol(".") + 1
|
|||
|
endif
|
|||
|
if line(".") > b:Vis_start_line
|
|||
|
let b:visheight = line(".") - b:Vis_start_line + 1
|
|||
|
else
|
|||
|
let b:visheight = b:Vis_start_line - line(".") + 1
|
|||
|
endif
|
|||
|
let b:vis_just_saved = 1
|
|||
|
let b:erase_or_drag = 'drag'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! VisWithSavedDims()
|
|||
|
if b:viswidth == 1 && b:visheight == 1
|
|||
|
return
|
|||
|
elseif b:viswidth == 1
|
|||
|
exe 'normal! '.(b:visheight-1).'jo'
|
|||
|
elseif b:visheight == 1
|
|||
|
exe 'normal! '.(b:viswidth-1).'lo'
|
|||
|
else
|
|||
|
exe 'normal! '.(b:viswidth-1).'l'.(b:visheight-1).'jo'
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! NoSketch()
|
|||
|
let &go = b:Sketch_savedguiopts
|
|||
|
let &mousemodel = b:Sketch_savedmousemodel
|
|||
|
setl ve=
|
|||
|
nunmap <buffer> <LeftMouse>
|
|||
|
nunmap <buffer> <LeftDrag>
|
|||
|
"Arrow
|
|||
|
nunmap <buffer> <2-LeftMouse>
|
|||
|
"Single vert bar
|
|||
|
nunmap <buffer> <3-LeftMouse>
|
|||
|
"Painting
|
|||
|
nunmap <buffer> <C-LeftMouse>
|
|||
|
nunmap <buffer> <C-LeftDrag>
|
|||
|
nunmap <buffer> <M-LeftMouse>
|
|||
|
nunmap <buffer> <M-2-LeftMouse>
|
|||
|
nunmap <buffer> <M-3-LeftMouse>
|
|||
|
nunmap <buffer> <M-4-LeftMouse>
|
|||
|
"Selection
|
|||
|
nunmap <buffer> <RightMouse>
|
|||
|
vunmap <buffer> <RightDrag>
|
|||
|
vunmap <buffer> <RightRelease>
|
|||
|
vunmap <buffer> <S-RightMouse>
|
|||
|
nunmap <buffer> <S-RightDrag>
|
|||
|
nunmap <buffer> <RightDrag>
|
|||
|
"Erase
|
|||
|
nunmap <buffer> <C-RightMouse>
|
|||
|
nunmap <buffer> <C-RightDrag>
|
|||
|
nunmap <buffer> <M-RightMouse>
|
|||
|
nunmap <buffer> <M-RightDrag>
|
|||
|
vunmap <buffer> <RightMouse>
|
|||
|
vunmap <buffer> <2-RightMouse>
|
|||
|
"Fill
|
|||
|
vunmap <buffer> <LeftMouse>
|
|||
|
vunmap <buffer> <S-LeftMouse>
|
|||
|
vunmap <buffer> <C-LeftMouse>
|
|||
|
nunmap <buffer> <S-LeftMouse>
|
|||
|
nunmap <buffer> <S-2-LeftMouse>
|
|||
|
nunmap <buffer> <S-3-LeftMouse>
|
|||
|
nunmap <buffer> <S-4-LeftMouse>
|
|||
|
nunmap <buffer> <leader>f
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchFillBrush(style) range
|
|||
|
if MarkVisEnd() == 'abort'
|
|||
|
return
|
|||
|
endif
|
|||
|
if a:style == 'opaque'
|
|||
|
exe "normal! gvr".b:brushes[0]
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchFillBox(style) range
|
|||
|
"Fixes bug 3.
|
|||
|
if MarkVisEnd() == 'abort'
|
|||
|
return
|
|||
|
endif
|
|||
|
if a:style == 'opaque'
|
|||
|
"TRAILING SPACE
|
|||
|
normal! gvr
|
|||
|
endif
|
|||
|
|
|||
|
if b:Vis_start_line < b:Vis_end_line
|
|||
|
let top = b:Vis_start_line
|
|||
|
let bot = b:Vis_end_line
|
|||
|
else
|
|||
|
let top = b:Vis_end_line
|
|||
|
let bot = b:Vis_start_line
|
|||
|
endif
|
|||
|
if b:Vis_start_col < b:Vis_end_col
|
|||
|
let left = b:Vis_start_col
|
|||
|
let right = b:Vis_end_col
|
|||
|
else
|
|||
|
let left = b:Vis_end_col
|
|||
|
let right = b:Vis_start_col
|
|||
|
endif
|
|||
|
|
|||
|
"Lots of bugginess if we are in virtual columns, so lets pad it first.
|
|||
|
let lnum = top
|
|||
|
while lnum <= bot
|
|||
|
let line = getline(lnum)
|
|||
|
"Handle lines with tabs
|
|||
|
"X:let len = strlen(line)
|
|||
|
exe "norm! " . lnum . "G"
|
|||
|
let len = virtcol("$") - 1
|
|||
|
if (len) < right "pad the line.
|
|||
|
let i = 1
|
|||
|
while i < (right - len)
|
|||
|
let line = line . ' '
|
|||
|
let i = i + 1
|
|||
|
endwhile
|
|||
|
call setline(lnum, line)
|
|||
|
endif
|
|||
|
let lnum = lnum + 1
|
|||
|
endwhile
|
|||
|
|
|||
|
"Don't draw corners. If we are just drawing a line then we want to check
|
|||
|
"for a join first. Need to test for greater than 1, not 0 because we are
|
|||
|
"not including corners.
|
|||
|
if (bot-top) > 1
|
|||
|
"Wake up vim. Also fixes bug 2, bug 6.
|
|||
|
normal! lh
|
|||
|
call Cursor(top,left)
|
|||
|
let n = (bot-top-2)==0 ? '' : (bot-top-2).'j'
|
|||
|
normal! lh
|
|||
|
exe 'normal! jlh'.n.'r|'
|
|||
|
call Cursor(top,right)
|
|||
|
normal! lh
|
|||
|
"Seems to be a bug. If I don't do lh after visual block selction, it goes
|
|||
|
"wrong.
|
|||
|
exe 'normal! jlh'.n.'r|'
|
|||
|
endif
|
|||
|
if (right-left) > 1
|
|||
|
"Also bugginess if we don't wake vim up with a cursor movement before
|
|||
|
"calling cursor()
|
|||
|
normal! l
|
|||
|
call Cursor(top,left)
|
|||
|
let n = (right-left-2)==0 ? '' : (right-left-2).'l'
|
|||
|
exe 'normal! llh'.n.'r-'
|
|||
|
normal! l
|
|||
|
call Cursor(bot,left)
|
|||
|
exe 'normal! llh'.n.'r-'
|
|||
|
endif
|
|||
|
|
|||
|
"Want to draw the '-' last, because we have triple click to insert a single
|
|||
|
"'|'. So now we can rightclick leftclick to insert a single '-' over a
|
|||
|
"character.
|
|||
|
if top == bot
|
|||
|
"Horizontal line.
|
|||
|
call Cursor(top,left)
|
|||
|
normal! lh
|
|||
|
if GetChar() == '|'
|
|||
|
normal! r+
|
|||
|
else
|
|||
|
normal! r-
|
|||
|
endif
|
|||
|
call Cursor(top,right)
|
|||
|
normal! lh
|
|||
|
if GetChar() == '|'
|
|||
|
normal! r+
|
|||
|
else
|
|||
|
normal! r-
|
|||
|
endif
|
|||
|
elseif left == right
|
|||
|
"Vertical line.
|
|||
|
call Cursor(top,left)
|
|||
|
normal! lh
|
|||
|
if GetChar() == '-'
|
|||
|
normal! r+
|
|||
|
else
|
|||
|
normal! r|
|
|||
|
endif
|
|||
|
call Cursor(bot,left)
|
|||
|
if GetChar() == '-'
|
|||
|
normal! r+
|
|||
|
else
|
|||
|
normal! r|
|
|||
|
endif
|
|||
|
else
|
|||
|
if b:roundcorners == 1
|
|||
|
call Cursor(top,left)
|
|||
|
normal! r.
|
|||
|
call Cursor(top,right)
|
|||
|
normal! r.
|
|||
|
call Cursor(bot,left)
|
|||
|
normal! r'
|
|||
|
call Cursor(bot,right)
|
|||
|
normal! r'
|
|||
|
else
|
|||
|
call Cursor(top,left)
|
|||
|
normal! r+
|
|||
|
call Cursor(top,right)
|
|||
|
normal! r+
|
|||
|
call Cursor(bot,left)
|
|||
|
normal! r+
|
|||
|
call Cursor(bot,right)
|
|||
|
normal! r+
|
|||
|
endif
|
|||
|
endif
|
|||
|
|
|||
|
call Cursor(b:Vis_end_line, b:Vis_end_col)
|
|||
|
" Determine shape of box to set the direction.
|
|||
|
"/2 because letters are narrower than they are tall.
|
|||
|
if (right-left)/2 >= (bot-top)
|
|||
|
"Short fat box.
|
|||
|
if b:Vis_end_col > b:Vis_start_col
|
|||
|
call SketchSavePos('r')
|
|||
|
else
|
|||
|
call SketchSavePos('l')
|
|||
|
endif
|
|||
|
else
|
|||
|
"Tall thin box.
|
|||
|
if b:Vis_end_line > b:Vis_start_line
|
|||
|
call SketchSavePos('d')
|
|||
|
else
|
|||
|
call SketchSavePos('u')
|
|||
|
endif
|
|||
|
endif
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! MoreLines(where)
|
|||
|
if a:where == 'below'
|
|||
|
let pos = SavePos(0)
|
|||
|
normal! G12o
|
|||
|
exe pos
|
|||
|
else
|
|||
|
let pos = SavePos(12)
|
|||
|
normal! 1G12O
|
|||
|
exe pos
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SavePos(offset)
|
|||
|
let c = virtcol(".")
|
|||
|
let l1 = line(".")
|
|||
|
normal! H
|
|||
|
let l2 = line(".")
|
|||
|
return 'call Cursor('.(l2 + a:offset).',1)| exe "normal! zt"|call Cursor('.(l1 + a:offset).',1)|exe "normal! '.(c-1).'l"'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchPaint()
|
|||
|
call SketchSavePos('auto')
|
|||
|
if b:brushes[0] == '.'
|
|||
|
normal! r.
|
|||
|
elseif b:brushes[0] == ':'
|
|||
|
normal! r:lr:h
|
|||
|
elseif b:brushes[0] == '#'
|
|||
|
normal! hr#lr#lr#hhjr#lr#lr#hk
|
|||
|
endif
|
|||
|
silent call AddLineIfAtBoundary()
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchErase(size) range
|
|||
|
if winnr() != g:Sketch_winnr
|
|||
|
return
|
|||
|
endif
|
|||
|
if a:size == 'vblock'
|
|||
|
if MarkVisEnd() == 'abort'
|
|||
|
return
|
|||
|
endif
|
|||
|
"TRAILING SPACE
|
|||
|
normal! gvr
|
|||
|
else
|
|||
|
if a:size == ''
|
|||
|
let size = b:Sketch_erasesize
|
|||
|
else
|
|||
|
let size = a:size
|
|||
|
endif
|
|||
|
if size == 'small'
|
|||
|
"TRAILING SPACE
|
|||
|
normal! r
|
|||
|
let b:Sketch_erasesize = size
|
|||
|
elseif size == 'big'
|
|||
|
normal! hkR hhjR hhjR hk
|
|||
|
let b:Sketch_erasesize = size
|
|||
|
endif
|
|||
|
call SketchSavePos('auto')
|
|||
|
silent call AddLineIfAtBoundary()
|
|||
|
endif
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
|
|||
|
fun! SketchClick(char)
|
|||
|
if a:char == '>'
|
|||
|
call SketchArrow()
|
|||
|
elseif a:char == '|'
|
|||
|
call SketchBar()
|
|||
|
else
|
|||
|
"This fixes bug 7.
|
|||
|
if IsBlankChar() || (GetChar() != '-' && GetChar() != '|')
|
|||
|
exe "normal! r" . a:char
|
|||
|
let b:Sketch_firstclick = 1
|
|||
|
else
|
|||
|
normal! r+
|
|||
|
let b:Sketch_firstclick = 0
|
|||
|
endif
|
|||
|
if a:char == '-'
|
|||
|
call SketchSavePos('r')
|
|||
|
else
|
|||
|
call SketchSavePos('d')
|
|||
|
endif
|
|||
|
endif
|
|||
|
silent call AddLineIfAtBoundary()
|
|||
|
endfun
|
|||
|
|
|||
|
fun! AddLineIfAtBoundary()
|
|||
|
"Tried adding line at top of file as well, but I didn't think it
|
|||
|
"worked very well.
|
|||
|
if line(".") == line("$")
|
|||
|
$ put _
|
|||
|
endif
|
|||
|
call Cursor(b:Sketch_line,b:Sketch_col)
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchArrow()
|
|||
|
if b:Sketch_dir2 == 'r'
|
|||
|
normal! r>
|
|||
|
elseif b:Sketch_dir2 == 'l'
|
|||
|
normal! r<
|
|||
|
elseif b:Sketch_dir2 == 'u'
|
|||
|
normal! r^
|
|||
|
elseif b:Sketch_dir2 == 'd'
|
|||
|
normal! rv
|
|||
|
endif
|
|||
|
call SketchSavePos(b:Sketch_dir2)
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchBar()
|
|||
|
normal! r|
|
|||
|
call SketchSavePos(b:Sketch_dir)
|
|||
|
endfun
|
|||
|
|
|||
|
fun! Debug()
|
|||
|
echo "Line: ".b:Sketch_line." Col: ".b:Sketch_col." Dir: ".b:Sketch_dir
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchDrag()
|
|||
|
"Moving vertically (current col == last saved col)
|
|||
|
if virtcol(".") == b:Sketch_col
|
|||
|
"This fixes bug 7.
|
|||
|
if IsBlankChar() || (GetChar() !~ '-\|+')
|
|||
|
normal! r|
|
|||
|
else
|
|||
|
normal! r+
|
|||
|
endif
|
|||
|
if b:Sketch_dir =~ 'r\|l'
|
|||
|
if b:Sketch_firstclick
|
|||
|
call SketchAtSavedPos('|')
|
|||
|
else
|
|||
|
if b:roundcorners == 1
|
|||
|
"Previously moved horizontally, now moving up
|
|||
|
if line(".") < b:Sketch_line
|
|||
|
call SketchAtSavedPos("'")
|
|||
|
"Moving down
|
|||
|
else
|
|||
|
call SketchAtSavedPos('.')
|
|||
|
endif
|
|||
|
else
|
|||
|
call SketchAtSavedPos('+')
|
|||
|
endif
|
|||
|
endif
|
|||
|
endif
|
|||
|
"[TODO] I think this is redundant, as rightrelease now sets this.
|
|||
|
if line(".") > b:Sketch_line
|
|||
|
call SketchSavePos('d')
|
|||
|
else
|
|||
|
call SketchSavePos('u')
|
|||
|
endif
|
|||
|
"Otherwise, must be moving horizontally
|
|||
|
else
|
|||
|
"This fixes bug 7.
|
|||
|
if IsBlankChar() || (GetChar() !~ '|\|+')
|
|||
|
normal! r-
|
|||
|
else
|
|||
|
normal! r+
|
|||
|
endif
|
|||
|
if b:Sketch_dir =~ 'd\|u'
|
|||
|
if b:roundcorners == 1
|
|||
|
"Was moving up
|
|||
|
if b:Sketch_dir == 'u'
|
|||
|
call SketchAtSavedPos(".")
|
|||
|
"Moving down
|
|||
|
else
|
|||
|
call SketchAtSavedPos("'")
|
|||
|
endif
|
|||
|
else
|
|||
|
call SketchAtSavedPos('+')
|
|||
|
endif
|
|||
|
endif
|
|||
|
"I think this is redundant, as rightrelease now sets this.
|
|||
|
if virtcol(".") > b:Sketch_col
|
|||
|
call SketchSavePos('r')
|
|||
|
else
|
|||
|
call SketchSavePos('l')
|
|||
|
endif
|
|||
|
endif
|
|||
|
let b:Sketch_firstclick = 0
|
|||
|
silent call AddLineIfAtBoundary()
|
|||
|
echo '['.b:brushes[0].']['.((b:roundcorners==1)?'Round':'Square').']'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! IsBlankChar()
|
|||
|
let char = GetChar()
|
|||
|
if (char == ' ') || (char == '')
|
|||
|
return 1
|
|||
|
else
|
|||
|
return 0
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! GetChar()
|
|||
|
return strpart(getline("."),virtcol(".")-1,1)
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchSavePos(dir)
|
|||
|
let b:Sketch_dir2 = b:Sketch_dir
|
|||
|
if a:dir == 'auto'
|
|||
|
if (line(".") > b:Sketch_line)
|
|||
|
let b:Sketch_dir = 'd'
|
|||
|
elseif (line(".") < b:Sketch_line)
|
|||
|
let b:Sketch_dir = 'u'
|
|||
|
elseif (virtcol(".") > b:Sketch_col)
|
|||
|
let b:Sketch_dir = 'r'
|
|||
|
elseif (virtcol(".") < b:Sketch_col)
|
|||
|
let b:Sketch_dir = 'l'
|
|||
|
endif
|
|||
|
else
|
|||
|
let b:Sketch_dir = a:dir
|
|||
|
endif
|
|||
|
let b:Sketch_line = line(".")
|
|||
|
let b:Sketch_col = virtcol(".")
|
|||
|
endfun
|
|||
|
|
|||
|
fun! SketchAtSavedPos(char)
|
|||
|
let col = virtcol(".")
|
|||
|
let line = line(".")
|
|||
|
call Cursor(b:Sketch_line,b:Sketch_col)
|
|||
|
exe "normal! r".a:char
|
|||
|
"You can have fun if you reverse line and col
|
|||
|
call Cursor(line,col)
|
|||
|
endfun
|
|||
|
|
|||
|
"
|
|||
|
"-- Flood fill functions -----------------------------------
|
|||
|
"
|
|||
|
fun! s:Field(string, num, delim)
|
|||
|
" Return the field specified by integer a:num from a:string where fields are
|
|||
|
" delimited by the character a:delim.
|
|||
|
if a:num < 1
|
|||
|
return ''
|
|||
|
elseif a:num == 1
|
|||
|
return matchstr(a:string, '[^' . a:delim . ']*')
|
|||
|
else
|
|||
|
return matchstr(a:string, '\([^' . a:delim . ']*' . a:delim . '\)\{' . (a:num - 1) . '}\zs[^' . a:delim . ']*')
|
|||
|
endif
|
|||
|
endfun
|
|||
|
|
|||
|
fun! s:Unlet()
|
|||
|
let i = 1
|
|||
|
while i <= s:TOS
|
|||
|
exe 'unlet s:fillinfo' . i
|
|||
|
let i = i + 1
|
|||
|
endwhile
|
|||
|
endfun
|
|||
|
|
|||
|
" The fill algorithm might as well be recursive. However Vim has reasonably
|
|||
|
" strict limits on the depth of recursion. It is quite hard to break this
|
|||
|
" algorithm if done recursively, but it is possible with a large complicated
|
|||
|
" diagram. Just in case this is a problem for someone, I've implemented the
|
|||
|
" algorithm imperatively, using a couple of explicit stacks. Happily, this
|
|||
|
" also seems to speed things up.
|
|||
|
"
|
|||
|
" The fill starts off horizontally. When a line has been filled as far as it
|
|||
|
" can, the line, the leftmost cell and the rightmost cell are pushed onto a
|
|||
|
" stack. Information from a stack is popped, and this is used to check each
|
|||
|
" cell above and below those just filled. If any of these are not a boundary
|
|||
|
" character then go back to the start of this paragraph.
|
|||
|
"
|
|||
|
" If I also encode the vertical direction in which the fill is progressing,
|
|||
|
" then I can make a simple optimization to reduce the number of cells that
|
|||
|
" need checking.
|
|||
|
|
|||
|
fun! s:PushFillInfo(line, L, R, dir) "dir can be 'u' up or 'd' down
|
|||
|
let s:TOS = s:TOS + 1
|
|||
|
exe 'let s:fillinfo' . s:TOS . '="' . a:line . ',' . a:L . ',' . a:R . ',' . a:dir . '"'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! s:PopFillInfo()
|
|||
|
exe 'let fillinfo = s:fillinfo' . s:TOS
|
|||
|
exe 'unlet s:fillinfo' . s:TOS
|
|||
|
let s:TOS = s:TOS - 1
|
|||
|
let line = s:Field(fillinfo, 1, ',')
|
|||
|
let L = s:Field(fillinfo, 2, ',')
|
|||
|
let R = s:Field(fillinfo, 3, ',')
|
|||
|
let dir = s:Field(fillinfo, 4, ',')
|
|||
|
return 'let line=' . line . '|let L=' . L . '|let R=' . R . '|let dir="' . dir . '"'
|
|||
|
endfun
|
|||
|
|
|||
|
fun! s:IsBoundary()
|
|||
|
return @" ==# s:fillchar || @" == '|' || @" == '-' || @" == '' || @" == '+' || @" == '\' || @" == '/' || @" == '<' || @" == '>'
|
|||
|
endfun
|
|||
|
|
|||
|
" Returns a string that you can execute to store the leftmost column in L and
|
|||
|
" the rightmost column in R. E.g. :exe Fill_line()
|
|||
|
fun! s:Fill_line()
|
|||
|
let line = line('.') | let col = col('.')
|
|||
|
"Fill current char
|
|||
|
let R = col | let L = col
|
|||
|
silent norm! yl
|
|||
|
if !s:IsBoundary()
|
|||
|
exe 'silent norm! r' . s:fillchar
|
|||
|
endif
|
|||
|
"Fill to the left
|
|||
|
let i = col
|
|||
|
let L = 1
|
|||
|
while i > 1
|
|||
|
silent norm! hyl
|
|||
|
let i = i - 1
|
|||
|
if s:IsBoundary()
|
|||
|
let L = i + 1
|
|||
|
break
|
|||
|
else
|
|||
|
exe 'silent norm! r' . s:fillchar
|
|||
|
endif
|
|||
|
endwhile
|
|||
|
call Cursor(line, col)
|
|||
|
"Fill to the right
|
|||
|
let i = col
|
|||
|
let R = col('$') - 1
|
|||
|
while i < (col('$') - 1)
|
|||
|
silent norm! lyl
|
|||
|
let i = i + 1
|
|||
|
if s:IsBoundary()
|
|||
|
let R = i - 1
|
|||
|
break
|
|||
|
else
|
|||
|
exe 'silent norm! r' . s:fillchar
|
|||
|
endif
|
|||
|
endwhile
|
|||
|
return 'let L=' . L . '|let R=' . R
|
|||
|
endfun
|
|||
|
|
|||
|
fun! <SID>Fill()
|
|||
|
" The variables used for the stack get unlet as the function progresses.
|
|||
|
" However if the user hits <C-C> before filling has finished, we could
|
|||
|
" potentially be left with many variables in memory. So each time Fill() is
|
|||
|
" run, first check that nothing is left over from the previous Fill(). If
|
|||
|
" it is then remove the variables before prompting the user for the fill
|
|||
|
" character. This way the user won't notice the delay.
|
|||
|
if exists("s:fillinfo1")
|
|||
|
call s:Unlet()
|
|||
|
endif
|
|||
|
let s:TOS = 0
|
|||
|
"Get input from user. Use only the first character supplied.
|
|||
|
call inputsave()
|
|||
|
let s:fillchar = input("Enter the fill character: ")[0]
|
|||
|
call inputrestore()
|
|||
|
if s:fillchar == ''
|
|||
|
redraw!
|
|||
|
echo 'Fill aborted.'
|
|||
|
return
|
|||
|
endif
|
|||
|
echo 'Working, please wait.'
|
|||
|
let saved_ve = &ve
|
|||
|
let &ve = ''
|
|||
|
let lastline = line('$')
|
|||
|
silent norm! yl
|
|||
|
if s:IsBoundary()
|
|||
|
redraw!
|
|||
|
echo 'On a boundary.'
|
|||
|
return
|
|||
|
endif
|
|||
|
let line = line('.') | let col = col('.')
|
|||
|
let restorecursor = "call Cursor(" . line . "," . col . ")"
|
|||
|
silent exe s:Fill_line()
|
|||
|
call s:PushFillInfo(line, L, R, 'u')
|
|||
|
call s:PushFillInfo(line, L, R, 'd')
|
|||
|
while s:TOS > 0
|
|||
|
exe s:PopFillInfo()
|
|||
|
let l = L | let r = R
|
|||
|
if dir == 'u'
|
|||
|
if line > 1
|
|||
|
exe 'silent norm! ' . (line - 1). 'G' . L . '|'
|
|||
|
else
|
|||
|
continue
|
|||
|
endif
|
|||
|
let i = l
|
|||
|
while i <= r
|
|||
|
silent norm! yl
|
|||
|
if !s:IsBoundary()
|
|||
|
silent exe s:Fill_line()
|
|||
|
call s:PushFillInfo(line - 1, L, R, 'u')
|
|||
|
" Eliminate some (but not all) of the cells already checked.
|
|||
|
" This is actually slightly faster than eliminating all the
|
|||
|
" cells already checked! (shown underneath). Perhaps because of
|
|||
|
" the extra stack accesses being more expensive than looping
|
|||
|
" over a few already checked cells?
|
|||
|
if R > r || L < l
|
|||
|
call s:PushFillInfo(line - 1, L, R, 'd')
|
|||
|
endif
|
|||
|
"if L < l
|
|||
|
" call s:PushFillInfo(line - 1, L, l - 1, 'd')
|
|||
|
"endif
|
|||
|
"if R > r
|
|||
|
" call s:PushFillInfo(line - 1, l + 1, R, 'd')
|
|||
|
"endif
|
|||
|
" Finish early if possible.
|
|||
|
if R >= r
|
|||
|
break
|
|||
|
else
|
|||
|
let i = R + 1
|
|||
|
endif
|
|||
|
else
|
|||
|
let i = i + 1
|
|||
|
endif
|
|||
|
exe 'silent norm! ' . i . '|'
|
|||
|
endwhile
|
|||
|
else "assume dir == 'd'
|
|||
|
if line < lastline
|
|||
|
exe 'silent norm! ' . (line + 1). 'G' . L . '|'
|
|||
|
else
|
|||
|
continue
|
|||
|
endif
|
|||
|
let i = l
|
|||
|
while i <= r
|
|||
|
silent norm! yl
|
|||
|
if !s:IsBoundary()
|
|||
|
silent exe s:Fill_line()
|
|||
|
call s:PushFillInfo(line + 1, L, R, 'd')
|
|||
|
" Eliminate some (but not all) of the cells already checked.
|
|||
|
if R > r || L < l
|
|||
|
call s:PushFillInfo(line + 1, L, R, 'u')
|
|||
|
endif
|
|||
|
"if L < l
|
|||
|
" call s:PushFillInfo(line + 1, L, l - 1, 'u')
|
|||
|
"endif
|
|||
|
"if R > r
|
|||
|
" call s:PushFillInfo(line + 1, l + 1, R, 'u')
|
|||
|
"endif
|
|||
|
" Finish early if possible.
|
|||
|
if R >= r
|
|||
|
break
|
|||
|
else
|
|||
|
let i = R + 1
|
|||
|
endif
|
|||
|
else
|
|||
|
let i = i + 1
|
|||
|
endif
|
|||
|
exe 'silent norm! ' . i . '|'
|
|||
|
endwhile
|
|||
|
endif
|
|||
|
endwhile
|
|||
|
redraw!
|
|||
|
let &ve = saved_ve
|
|||
|
exe restorecursor
|
|||
|
echo 'Fill finished.'
|
|||
|
endfun
|
|||
|
|
|||
|
|
|||
|
"
|
|||
|
"Implement diagonals like this:
|
|||
|
" /
|
|||
|
" \/
|
|||
|
" /\ _
|
|||
|
" / \ /|
|
|||
|
" _ _ .----------------' \ /
|
|||
|
" /| |\ \ / / X
|
|||
|
" / \ \| |/ / / \
|
|||
|
" <20> <20> / \
|
|||
|
"
|
|||
|
"
|
|||
|
"Implement painting with colours like this:
|
|||
|
"syn match y /y/
|
|||
|
"syn match x /x/
|
|||
|
"hi y guifg=#cc7788 guibg=#cc7788
|
|||
|
"hi x guifg=#8877cc guibg=#8877cc
|
|||
|
"map \x :let brush = 'x'<CR>
|
|||
|
"map \y :let brush = 'y'<CR>
|
|||
|
"map <rightdrag> <leftmouse>:exe 'normal! r'.brush <CR>
|
|||
|
"map <rightmouse> <leftmouse>:exe 'normal! r'.brush <CR>
|
|||
|
"
|
|||
|
" Even though Sketch doesn't have diagonals yet,
|
|||
|
" this was easy thanks to the copy+drag actions.
|
|||
|
" +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
" |\...........\...........\...........\...........\...........\...........\...........\...........\
|
|||
|
" |:\...........\...........\...........\...........\...........\...........\...........\...........\
|
|||
|
" |::+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
" |::|\...........\...........\ |::| |::| |::| |::|\...........\...........\
|
|||
|
" |::|:\...........\...........\ |::| |::| |::| |::|:\...........\...........\
|
|||
|
" +::|::+-----------+-----------+-----+::|--------+::|--------+::|--------+::|::+-----------+-----------+
|
|||
|
" |\:|::|\...........\...........\.....\:|.........\:|.........\:|.........\:|::|\...........\...........\
|
|||
|
" |:\|::|:\...........\...........\.....\|..........\|..........\|..........\|::|:\...........\...........\
|
|||
|
" |::+::|::+-----------+-----------+-----+-----------+-----------+-----------+::|::+-----------+-----------+
|
|||
|
" |::|\:|::|\...........\...........\ |::| |::| |::| |::|\:|::|\...........\...........\
|
|||
|
" |::|:\|::|:\...........\...........\|::| |::| |::| |::|:\|::|:\...........\...........\
|
|||
|
" +::|::+::|::+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
" \:|::|\:|::|\...........\...........\...........\...........\...........\...........\...........\...........\
|
|||
|
" \|::|:\|::|:\...........\...........\...........\...........\...........\...........\...........\...........\
|
|||
|
" +::|::|::|::+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
" \:|::|\:|::|......\:|::|......\:|::| |::| |::| |::|\:|::|\:|::|......\:|::|......\:|::|
|
|||
|
" \|::|:\|::|.......\|::|.......\|::| |::| |::| |::| \|::|:\|::|.......\|::|.......\|::|
|
|||
|
" +::|::+::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|
|
|||
|
" \:|::|\:|.........\:|.........\.|.........\:|.........\:|.........\:|.........\:|.........\:|.........\:|
|
|||
|
" \|::|:\|..........\|..........\|..........\|..........\|..........\|..........\|..........\|..........\|
|
|||
|
" +::|::+-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
" \:|::|......\:|::|......\:|::| |::| |::| |::| \:|::|......\:|::|......\:|::|
|
|||
|
" \|::|.......\|::|.......\|::| |::| |::| |::| \|::|.......\|::|.......\|::|
|
|||
|
" +::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|--------+::|
|
|||
|
" \:|.........\:|.........\:|.........\:|.........\:|.........\:|.........\:|.........\:|.........\:|
|
|||
|
" \|..........\|..........\|..........\|..........\|..........\|..........\|..........\|..........\|
|
|||
|
" +-----------+-----------+-----------+-----------+-----------+-----------+-----------+-----------+
|
|||
|
"
|
|||
|
"
|
|||
|
" +--------------------+ +--------------------+ +--------------------+ +--------------------+
|
|||
|
" | | | | | | | |
|
|||
|
" +---|----------------+ | +---|----------------+ | +---|----------------+ | +---|----------------+ |
|
|||
|
" | | | | | | | | | | | | | | | |
|
|||
|
" | | +--------------------+ | +--------------------| | +--------------------+ | +--------------------+
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | +---|----------------+ | +---|----------------+ | +---|----------------+ | +---|----------------+ |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | |---|----------------| | |---|----------------| | |---|----------------| | |---|----------------| |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" +---|---|------------+ | |---|---|------------+ | +---|---|------------+ | |---|---|------------+ | |
|
|||
|
" |---|----------------| | |---|----------------| | |---|----------------| | |---|----------------| |
|
|||
|
" | +--------------------+ | +--------------------+ | +--------------------+ | +--------------------+
|
|||
|
" +---|----------------+ | +---|----------------+ | +---|----------------+ | +---|----------------+ |
|
|||
|
" | +--------------------+ | +--------------------+ | +--------------------+ | +--------------------+
|
|||
|
" | | +--------------------+ | +--------------------| | +--------------------+ | +--------------------+
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | +---|----------------+ | +---|----------------+ | +---|----------------+ | +---|----------------+ |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" | |---|----------------| | |---|----------------| | |---|----------------| | |---|----------------| |
|
|||
|
" | | | | | | | | | | | | | | | | | | | | |
|
|||
|
" +---|---|------------+ | |---|---|------------+ | +---|---|------------+ | |---|---|------------+ | |
|
|||
|
" | | | | | | | | | | | | | | | |
|
|||
|
" | +--------------------+ | +--------------------+ | +--------------------+ | +--------------------+
|
|||
|
" | | | | | | | |
|
|||
|
" +--------------------+ +--------------------+ +--------------------+ +--------------------+
|
|||
|
"
|
|||
|
"
|
|||
|
"
|
|||
|
" Not that you'd ever want to draw anything like this, but it is easy. Big
|
|||
|
" screen helps :-)
|