' qfigsub.bas

'$INCLUDE: 'QB.BI'
'rem $INCLUDE: 'C:\QB45\USERLIB\GRAPH.BI'
'REM $INCLUDE: 'MOUSE.BI'
'$INCLUDE: 'QFIG.BI'

FUNCTION Angle (x0, y0, x1, y1)
'                                                                    arc sin
Angle = 0!: a = 0!
rad = SQR((x1 - x0) ^ 2 + (y1 - y0) ^ 2)
IF rad = 0! THEN EXIT FUNCTION
IF x1 = x0 THEN
 a = SGN(y0 - y1) * pi / 2!
 IF a < 0! THEN a = a + 2! * pi
ELSE
 a = ATN((y1 - y0) / (x0 - x1))
 IF x1 > x0 AND a < 0! THEN
       a = a + 2! * pi
 ELSEIF x1 < x0 THEN
       a = a + pi
 END IF
END IF
Angle = a
'
END FUNCTION

SUB D.Circles (cx%, cy%, rad, ratio, sang, eang, clr%, thickness%, simple%, wpatt%)
'                                     circle/ellipse drawings with thickness
IF ratio > 0 THEN
 CIRCLE (cx%, cy%), INT(rad), clr%, , , ratio
 IF simple% <> 1 THEN
       IF ratio >= 1! THEN
         rt1 = INT(rad): rt2 = INT(rad) / ratio
       ELSE
         rt1 = ratio * INT(rad): rt2 = INT(rad)
       END IF
       IF thickness% > 0 THEN CIRCLE (cx%, cy%), INT(rad) - 1, clr%, , , (rt1 - 1) / (rt2 - 1)
       IF thickness% > 1 THEN CIRCLE (cx%, cy%), INT(rad) + 1, clr%, , , (rt1 + 1) / (rt2 + 1)
 END IF
 rrt1 = rad / ratio: rrt2 = rad
 IF ratio < 1! THEN rrt2 = rad * ratio: rrt1 = rad
 IF simple% = -1 THEN
       MaxMin cx% + rrt1, cy% + rrt2: MaxMin cx% - rrt1, cy% - rrt2
 END IF
ELSE
 sang1 = sang: eang1 = eang
 IF sang < 0 THEN sang1 = 0!: eang1 = 2! * pi
 CIRCLE (cx%, cy%), INT(rad), clr%, sang1, eang1, 1
 IF simple% <> 1 THEN
       IF thickness% > 0 THEN CIRCLE (cx%, cy%), INT(rad) - 1, clr%, sang1, eang1, 1
       IF thickness% > 1 THEN CIRCLE (cx%, cy%), INT(rad) + 1, clr%, sang1, eang1, 1
 END IF
 IF simple% = -1 THEN
       IF sang < 0 THEN
         MaxMin cx% + rad, cy% + rad: MaxMin cx% - rad, cy% - rad
       ELSE
         MaxMin cx% + rad * COS(sang), cy% - rad * SIN(sang)
         MaxMin cx% + rad * COS(eang), cy% - rad * SIN(eang)
         IF sang < eang THEN
               IF eang > pi / 2! AND sang < pi / 2! THEN MaxMin cx%, cy% - rad
               IF eang > pi AND sang < pi THEN MaxMin cx% - rad, cy%
               IF eang > 3! * pi / 2! AND sang < 3! * pi / 2! THEN MaxMin cx%, cy% + rad
         ELSE
               MaxMin cx% + rad, cy%
               IF eang > pi / 2! OR (eang < pi / 2! AND sang < pi / 2!) THEN MaxMin cx%, cy% - rad
               IF eang > pi OR (eang < pi AND sang < pi) THEN MaxMin cx% - rad, cy%
               IF eang > 3! * pi / 2! OR (eang < 3! * pi / 2! AND sang < 3! * pi / 2!) THEN MaxMin cx%, cy% + rad
         END IF
       END IF
 END IF
END IF
'
END SUB

SUB D.Lines (sx%, sy%, ex%, ey%, clr%, box%, thickness%, linetype%, filltype%, simple%)
'                             line/box drawings with thickness/linetype/fill
SELECT CASE box%
 CASE 0
       LINE (sx%, sy%)-(ex%, ey%), clr%, , ltp%(linetype%)
 CASE 1
       LINE (sx%, sy%)-(ex%, ey%), clr%, B, ltp%(linetype%)
 CASE 2
       LINE (sx%, sy%)-(ex%, ey%), 2, B
       IF filltype% <> 0 AND (sx% - ex%) * (sy% - ey%) <> 0 THEN
         IF clr% <> 0 THEN
               PAINT ((sx% + ex%) / 2, (sy% + ey%) / 2), tlp$(filltype%), 2
         ELSE
               PAINT ((sx% + ex%) / 2, (sy% + ey%) / 2), 0, 2
         END IF
       END IF
       IF wkill% = 1 AND clr% = 0 THEN
              LINE (sx%, sy%)-(ex%, ey%), clr%, BF
              wkill% = 0
       ELSE
              LINE (sx%, sy%)-(ex%, ey%), clr%, B
       END IF
END SELECT
IF simple% <> 1 AND thickness% <> 0 THEN
 SELECT CASE box%
       CASE 0
         dx% = 1: dy% = 0
         IF ABS(ex% - sx%) > ABS(ey% - sy%) THEN dx% = 0: dy% = 1
         LINE (sx% - dx%, sy% - dy%)-(ex% - dx%, ey% - dy%), clr%, , ltp%(linetype%)
         IF thickness% > 1 THEN
               LINE (sx% + dx%, sy% + dy%)-(ex% + dx%, ey% + dy%), clr%, , ltp%(linetype%)
         END IF
       CASE ELSE
         dx% = SGN(ex% - sx%): dy% = SGN(ey% - sy%)
         a% = ltp%(linetype%): IF box% = 2 THEN a% = ltp%(0)
         LINE (sx% + dx%, sy% + dy%)-(ex% - dx%, ey% - dy%), clr%, B, a%
         IF thickness% > 1 THEN
               LINE (sx% - dx%, sy% - dy%)-(ex% + dx%, ey% + dy%), clr%, B, a%
         END IF
 END SELECT
END IF
'
IF simple% = -1 THEN MaxMin sx%, sy%: MaxMin ex%, ey%
'
END SUB

SUB D.Strings (n%, clr%, simple%)
'                                                            display strings
sx% = xx(n%, 0): sy% = yy(n%, 0)
ipt = 0!: kanji% = 0: sylow% = 0: syhigh% = 0
IF simple% <> 1 THEN
 special% = 0: script% = 0                                 'KPUT is special
 WINDOW SCREEN (0, 0)-(windowx%(wndwfctr%), windowy%(wndwfctr%))
 wt% = obj%(n%, 1)
 IF wtext% = 1 THEN wt% = 1
 FOR i% = 1 TO wt%
 IF yy(n%, i%) = 0! THEN
       a$ = CHR$(xx(n%, i%))
       IF special% = 0 AND a$ = "\" THEN special% = 1: GOTO one.char.done
       IF INSTR("^\@_", a$) <> 0 THEN
         IF special% = 0 AND INSTR("^@_", a$) <> 0 THEN
               SELECT CASE a$
                 CASE "^"
                       script% = 1
                       syhigh% = INT(scrpt(1) * obj%(n%, 4) + .9)
                 CASE "_"
                       script% = 2
                       sylow% = -INT(scrpt(2) * obj%(n%, 4) + .9)
                 CASE ELSE
                       script% = 0
               END SELECT
               GOTO one.char.done
         ELSE
               special% = 0
         END IF
       ELSEIF special% = 1 THEN
         special% = 0
       END IF
       IF ASC(a$) < &H20 OR ASC(a$) > &H7E THEN a$ = " "
       scriptsize = 1!: IF script% <> 0 THEN scriptsize = .7
       jpt = 8
 ELSE
       kanji% = 1
       a$ = STRING$(1, VAL("&j" + HEX$(yy(n%, i%)) + HEX$(xx(n%, i%))))
       jpt = CSNG(obj%(n%, 4) * jpitch%) / 250! * ptmm
 END IF
 ssx% = sx% + INT(ipt) - pxo%
 ssy% = sy% - INT(scrpt(script%) * obj%(n%, 4)) - pyo%
 ssx% = INT(CSNG(ssx%) / wndwxy(wndwfctr%))
 ssy% = INT(CSNG(ssy%) / wndwxy(wndwfctr%))
 IF ssx% + INT(jpt) > pxmax% - pxo% OR ssx% + INT(jpt) < pxmin% - pxo% THEN GOTO one.char.skipped
 IF ssy% > pymax% - pyo% OR ssy% < pymin% - pyo% THEN EXIT FOR
 IF clr% <> 0 THEN
       ptext ssx%, ssy%, a$, chattr%(obj%(n%, 5), 0), 0
 ELSE
       ptext ssx%, ssy%, a$, 0, 0
 END IF
one.char.skipped:
 ipt = ipt + jpt
one.char.done:
 NEXT i%                                                          'retrieve
 WINDOW SCREEN (pxo%, pyo%)-(pxo% + windowx%(wndwfctr%), pyo% + windowy%(wndwfctr%))
 IF simple% = -1 THEN
       MaxMin sx%, sy% - sylow%
       sysy = eheight(obj%(n%, 5)): IF kanji% = 1 THEN sysy = jheight(obj%(n%, 5))
       MaxMin sx% + INT(ipt), sy% + INT(sysy * obj%(n%, 4) * ptmm / .25) + syhigh%
 END IF
ELSE
 ipt = 0!: special% = 0: script% = 0
 FOR i% = 1 TO obj%(n%, 1)
 IF yy(n%, i%) = 0! THEN
       a$ = CHR$(xx(n%, i%))
       IF special% = 0 AND a$ = "\" THEN special% = 1: GOTO one.simple.done
       IF INSTR("^\@_", a$) <> 0 THEN
         IF special% = 0 AND INSTR("^@_", a$) <> 0 THEN
               SELECT CASE a$
                 CASE "^"
                       script% = 1
                 CASE "_"
                       script% = 2
                 CASE ELSE
                       script% = 0
               END SELECT
               GOTO one.simple.done
         ELSE
               special% = 0
         END IF
       ELSEIF special% = 1 THEN
         special% = 0
       END IF
       IF ASC(a$) < &H20 OR ASC(a$) > &H7E THEN a$ = " "
       scriptsize = 1!: IF script% <> 0 THEN scriptsize = .7
       ipt = ipt + CSNG(INT(scriptsize * obj%(n%, 4)) * epitch%(obj%(n%, 5), ASC(a$) - &H20)) / 250! * ptmm
 ELSE
       ipt = ipt + CSNG(obj%(n%, 4) * jpitch%) / 250! * ptmm
       kanji% = 1
 END IF
one.simple.done:
 NEXT i%
 sysy = eheight(obj%(n%, 5)): IF kanji% = 1 THEN sysy = jheight(obj%(n%, 5))
 LINE (sx%, sy%)-(sx% + INT(ipt), sy% + INT(sysy * obj%(n%, 4) * ptmm / .25)), clr%, B
END IF
'
END SUB

SUB FillPattern
'                                          fill pattern set, silly isn't it?
fill% = fill% + 1: IF fill% > UBOUND(filler%) THEN fill% = 0
'
END SUB

SUB G.Addnode (o%, n%, editcc%)
'                                add one node when even-nodes curve is input
IF n% = 1 THEN
 x.new% = (xx(o%, 0) + xx(o%, 1)) / 2!: y.new% = (yy(o%, 0) + yy(o%, 1)) / 2!
 j% = 0
ELSE
 dist = 0!
 FOR i% = 0 TO n% - 1
 dist1 = SQR((xx(o%, i%) - xx(o%, i% + 1)) ^ 2 + (yy(o%, i%) - yy(o%, i% + 1)) ^ 2)
 IF dist1 > dist THEN j% = i%: dist = dist1
 NEXT i%: t% = 0: IF j% = n% - 1 THEN t% = 1
 x0% = xx(o%, j% - t%): y0% = yy(o%, j% - t%)
 x1% = xx(o%, j% + 1 - t%): y1% = yy(o%, j% + 1 - t%)
 x2% = xx(o%, j% + 2 - t%): y2% = yy(o%, j% + 2 - t%)
 G.XYparam x0%, y0%, x1%, y1%, x2%, y2%, ax, bx, cx, ay, by, cy
 t = CSNG(t%) + .5
 x.new% = ax * t * t + bx * t + cx: y.new% = ay * t * t + by * t + cy
END IF
FOR i% = n% TO j% + 1 STEP -1
xx(o%, i% + 1) = xx(o%, i%): yy(o%, i% + 1) = yy(o%, i%): NEXT i%
xx(o%, j% + 1) = x.new%: yy(o%, j% + 1) = y.new%
'***** Mark Closed Curve which was originally a Poly ****
IF editcc% = 1 THEN obj%(o%, 6) = j% + 1
'********************************************************
n% = n% + 1
FOR i% = 1 TO 3: obj%(o%, i%) = obj%(o%, i%) + 1: NEXT i%
'
END SUB

SUB G.Arc
'                                                                        arc
job% = 3
KeySwitch 0
'LOCATE line2%, 24: COLOR 11: PRINT kky$(4);
COLOR 7
SetInst job%
wx1% = 24 * 8 - 8
wx2% = 24 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(4), 0, 1
'
startarc:
DO
 CursorMotion keyin%
LOOP UNTIL keyin% <> 1
VIEW SCREEN (0, 0)-(windowx%(0), winpy%)
IF keyin% >= 3 THEN GOTO donearc
pxold% = px%: pyold% = py%
xx(nobj%, 0) = px%: yy(nobj%, 0) = py%
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 LINE (xx(nobj%, 0), yy(nobj%, 0))-(pxold%, pyold%), 0
 IF keyin% = 4 THEN CursorDisplay px%, py%: GOTO donearc
 LINE (xx(nobj%, 0), yy(nobj%, 0))-(px%, py%), 7
 pxold% = px%: pyold% = py%
 CursorDisplay px%, py%
LOOP UNTIL keyin% <> 1
xx(nobj%, 2) = px%: yy(nobj%, 2) = py%: ok% = 1
DO
 CursorMotion keyin%
 tol = SQR((xx(nobj%, 0) - xx(nobj%, 2)) ^ 2 + (yy(nobj%, 0) - yy(nobj%, 2)) ^ 2)
 tol1 = SQR((px% - xx(nobj%, 2)) ^ 2 + (py% - yy(nobj%, 2)) ^ 2)
 tol1 = tol1 + SQR((px% - xx(nobj%, 0)) ^ 2 + (py% - yy(nobj%, 0)) ^ 2) - tol
 IF tol <> 0 THEN tol = tol1 / tol
 CursorDisplay px%, py%
 IF ok% = 1 THEN
       LINE (xx(nobj%, 0), yy(nobj%, 0))-(xx(nobj%, 2), yy(nobj%, 2)), 0
 ELSE
       CIRCLE (x0, y0), rad, 0, r1, r3, 1
 END IF
 IF keyin% = 4 THEN CursorDisplay px%, py%: GOTO donearc
 IF tol < .001 THEN
       LINE (xx(nobj%, 0), yy(nobj%, 0))-(xx(nobj%, 2), yy(nobj%, 2)), 7
       ok% = 1
 ELSE
       ok% = 0
       a = xx(nobj%, 0) - px%: B = yy(nobj%, 0) - py%
       c = px% - xx(nobj%, 2): D = py% - yy(nobj%, 2)
       E = xx(nobj%, 0) ^ 2 - CSNG(px%) * CSNG(px%)
       f = yy(nobj%, 0) ^ 2 - CSNG(py%) * CSNG(py%)
       G = CSNG(px%) * CSNG(px%) - xx(nobj%, 2) ^ 2
       h = CSNG(py%) * CSNG(py%) - yy(nobj%, 2) ^ 2
       y0 = ((E + f) * c - (G + h) * a) / (B * c - D * a) / 2!
       IF a <> 0! THEN
         x0 = (E + f - 2! * B * y0) / a / 2!
       ELSE
         x0 = (G + h - 2! * D * y0) / c / 2!
       END IF
       rad = SQR((xx(nobj%, 2) - x0) ^ 2 + (yy(nobj%, 2) - y0) ^ 2)
       r3 = Angle(x0, y0, xx(nobj%, 2), yy(nobj%, 2))
       r1 = Angle(x0, y0, xx(nobj%, 0), yy(nobj%, 0))
       r2 = Angle(x0, y0, CSNG(px%), CSNG(py%))
       IF (r3 < r2 AND r2 < r1) OR ((r1 < r3) AND (r2 < r1 OR r3 < r2)) THEN
         SWAP r1, r3: SWAP xx(nobj%, 0), xx(nobj%, 2)
         SWAP yy(nobj%, 0), yy(nobj%, 2)
       END IF
       CIRCLE (x0, y0), rad, 7, r1, r3, 1
 END IF
 CursorDisplay px%, py%
LOOP UNTIL keyin% = 3
CursorDisplay px%, py%
IF ok% = 1 THEN
 LINE (xx(nobj%, 0), yy(nobj%, 0))-(xx(nobj%, 2), yy(nobj%, 2)), 0
ELSE
 CIRCLE (x0, y0), rad, 0, r1, r3, 1
END IF
CursorDisplay px%, py%
xx(nobj%, 0) = x0 + rad * COS(r1): yy(nobj%, 0) = y0 - rad * SIN(r1)
xx(nobj%, 1) = x0: yy(nobj%, 1) = y0
xx(nobj%, 2) = x0 + rad * COS(r3): yy(nobj%, 2) = y0 - rad * SIN(r3)
xx(nobj%, 3) = rad: yy(nobj%, 3) = r1: yy(nobj%, 4) = r3
obj%(nobj%, 0) = 6: obj%(nobj%, 1) = 4
obj%(nobj%, 2) = 2: obj%(nobj%, 3) = -1
obj%(nobj%, 4) = thick%: obj%(nobj%, 5) = 0: obj%(nobj%, 6) = 0
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
GOTO startarc
'
donearc:
SetInst job%
KeySwitch 1
job% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 24: COLOR 3: PRINT kky$(4); : COLOR 7
'
END SUB

SUB G.ArrowDirec (sobj%, snode%, n%)
'                                           calculate the direction of arrow
SELECT CASE fnoo%(sobj%)
 CASE 1
       IF snode% = 0 THEN
         x3% = xx(sobj%, 1): y3% = yy(sobj%, 1)
       ELSE
         x3% = xx(sobj%, obj%(sobj%, 1) - 1)
         y3% = yy(sobj%, obj%(sobj%, 1) - 1)
       END IF
       GOSUB arrowarrow
 CASE 3
       k% = 0: t = .2: IF snode% <> 0 THEN k% = snode% - 2: t = 1.8
       x2% = xx(sobj%, k% + 2): y2% = yy(sobj%, k% + 2)
       x1% = xx(sobj%, k% + 1): y1% = yy(sobj%, k% + 1)
       x0% = xx(sobj%, k%): y0% = yy(sobj%, k%)
       G.XYparam x0%, y0%, x1%, y1%, x2%, y2%, ax, bx, cx, ay, by, cy
       x3% = ax * t * t + bx * t + cx: y3% = ay * t * t + by * t + cy
       GOSUB arrowarrow
 CASE 6
       x1% = xx(sobj%, snode%): y1% = yy(sobj%, snode%)
       s2 = yy(sobj%, 3) + 3! * pi / 2! + arcarrowd
       IF snode% <> 0 THEN s2 = yy(sobj%, 4) + pi / 2! - arcarrowd
END SELECT
arrow = arrowhead + darrowhead * obj%(n%, 4)
xx(n%, 2) = x1% - arrow * COS(s2 + arrowdirect)
yy(n%, 2) = y1% + arrow * SIN(s2 + arrowdirect)
xx(n%, 0) = x1% - arrow * COS(s2 - arrowdirect)
yy(n%, 0) = y1% + arrow * SIN(s2 - arrowdirect)
xx(n%, 1) = x1%: yy(n%, 1) = y1%
EXIT SUB
'
arrowarrow:
x1% = xx(sobj%, snode%): y1% = yy(sobj%, snode%)
IF x1% = x3% THEN
 s2 = SGN(y3% - y1%) * pi / 2!
ELSE
 s2 = ATN(CSNG(y3% - y1%) / CSNG(x1% - x3%))
 IF x1% < x3% THEN s2 = s2 + pi
END IF
RETURN
'
END SUB

SUB G.Arrows
'                                                                 set arrows
MarkEnds c%: IF c% = 0 THEN EXIT SUB
job% = 6
KeySwitch 0
SetInst job%
wx1% = 61 * 8 - 8
wx2% = 61 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(8), 0, 1
'
startarrow:
selh% = 1
DO
 CursorMotion keyin%
LOOP UNTIL keyin% <> 1
IF keyin% = 4 THEN GOTO donearrow
sobj% = -1
FOR i% = 0 TO nobj% - 1
IF fnoo%(i%) <> 1 AND fnoo%(i%) <> 3 AND fnoo%(i%) <> 6 THEN GOTO nogetends
selh% = 0
dist = SQR((xx(i%, 0) - px%) ^ 2 + (yy(i%, 0) - py%) ^ 2)
IF dist < 3 THEN snode% = 0: sobj% = i%: EXIT FOR
dist = SQR((xx(i%, obj%(i%, 2)) - px%) ^ 2 + (yy(i%, obj%(i%, 2)) - py%) ^ 2)
IF dist < 3 THEN snode% = obj%(i%, 2): sobj% = i%: EXIT FOR
nogetends: NEXT i%
IF sobj% < 0 THEN GOTO startarrow
G.Arrowset sobj%, snode%, already%
IF already% = 0 THEN nobj% = nobj% + 1: Object.Max.Check
IF keyin% = 3 THEN
 IF snode% = 0 THEN snode% = obj%(sobj%, 2) ELSE snode% = 0
 G.Arrowset sobj%, snode%, already%
 IF already% <> 0 THEN GOTO startarrow
 nobj% = nobj% + 1
 Object.Max.Check
END IF
GOTO startarrow
'
donearrow:
MarkEnds c%
SetInst job%
KeySwitch 1
job% = 0
selh% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 61: COLOR 3: PRINT kky$(8); : COLOR 7
'
END SUB

SUB G.Arrowset (sobj%, snode%, already%)
'                                                          arrow set & check
already% = 0
FOR i% = 0 TO nobj% - 1
IF fnoo%(i%) <> 11 THEN GOTO skipsrchar
IF obj%(i%, 5) = sobj% AND obj%(i%, 6) = snode% THEN
 already% = 1
 CursorDisplay px%, py%
 PPUT xx(sobj%, snode%) - 3, yy(sobj%, snode%) - 3, mark%()
 Killer i%, sobj%
 SetObject sobj%, 7, 0
 PPUT xx(sobj%, snode%) - 3, yy(sobj%, snode%) - 3, mark%()
 CursorDisplay px%, py%
 EXIT SUB
END IF
skipsrchar: NEXT i%
'
obj%(nobj%, 0) = 11: obj%(nobj%, 1) = 2: obj%(nobj%, 2) = -1
obj%(nobj%, 3) = -2: obj%(nobj%, 4) = obj%(sobj%, 4)
obj%(nobj%, 5) = sobj%: obj%(nobj%, 6) = snode%
G.ArrowDirec sobj%, snode%, nobj%
'
CursorDisplay px%, py%
PPUT xx(sobj%, snode%) - 3, yy(sobj%, snode%) - 3, mark%()
SetObject nobj%, 7, 0
PPUT xx(sobj%, snode%) - 3, yy(sobj%, snode%) - 3, mark%()
CursorDisplay px%, py%
'
END SUB

SUB G.Box
'                                                                        box
job% = 4
KeySwitch 0
SetInst job%
wx1% = 31 * 8 - 8
wx2% = 31 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(5), 0, 1
'
startbox:
'fill% = 0
DO
 CursorMotion keyin%
'  IF keyin% = 3 THEN FillPattern
LOOP UNTIL keyin% <> 1
VIEW SCREEN (0, 0)-(windowx%(0), winpy%)
IF keyin% = 4 THEN GOTO donebox
sx% = px%: sy% = py%: pxold% = px%: pyold% = py%
sxg% = sx%: syg% = sy%
inbox% = 1
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 IF fill% <> 0 THEN
       LINE (sx%, sy%)-(pxold%, pyold%), 2, B
       PAINT ((sx% + pxold%) / 2, (sy% + pyold%) / 2), 0, 2
 END IF
 LINE (sx%, sy%)-(pxold%, pyold%), 0, BF
 IF keyin% = 4 THEN CursorDisplay px%, py%: GOTO donebox
'  IF keyin% = 3 THEN FillPattern
 LINE (sx%, sy%)-(px%, py%), 0, BF
 IF fill% = 0 THEN
       LINE (sx%, sy%)-(px%, py%), 7, B
 ELSE
       LINE (sx%, sy%)-(px%, py%), 2, B
       PAINT ((sx% + px%) / 2, (sy% + py%) / 2), tlp$(fill%), 2
 END IF
 CursorDisplay px%, py%
 pxold% = px%: pyold% = py%
LOOP UNTIL keyin% = 2 OR keyin% = 3
inbox% = 0
CursorDisplay px%, py%
IF fill% <> 0 THEN
 LINE (sx%, sy%)-(px%, py%), 2, B
 PAINT ((sx% + px%) / 2, (sy% + py%) / 2), 0, 2
END IF
LINE (sx%, sy%)-(px%, py%), 0, B
CursorDisplay px%, py%
xx(nobj%, 0) = sx%: yy(nobj%, 0) = sy%
xx(nobj%, 1) = px%: yy(nobj%, 1) = py%
obj%(nobj%, 0) = 8: obj%(nobj%, 1) = 1
IF fill% <> 0 THEN obj%(nobj%, 0) = 9
obj%(nobj%, 2) = 1: obj%(nobj%, 3) = -1
obj%(nobj%, 4) = thick%: obj%(nobj%, 5) = ltype%
obj%(nobj%, 6) = 0: obj%(nobj%, 6) = fill%
IF fill% <> 0 THEN obj%(nobj%, 5) = 0
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check

' --------
' Box Text, yes/no?
ipy% = py%: ipx% = px%: L.Text ipx%, ipy%
PRINT "Text(y/n)??";
bkey$ = yesno$
L.Text ipx%, ipy%: PRINT SPACE$(12);
IF bkey$ = "n" THEN GOTO startbox
'--------

'                                                                   string
job% = 5
KeySwitch 0
LOCATE line2%, 68: COLOR 11: PRINT kky$(9); : COLOR 7
SetInst job%
wx1% = 68 * 8 - 8
wx2% = 68 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF

'
pxold% = px%: pyold% = py%
'------
' Calculate Box center for Box text
px% = sx% + (pxold% - sx%) / 2
py% = sy% + (pyold% - sy%) / 2 - texth% + 4
'------

pxold% = px%: pyold% = py%
CursorDisplay px%, py%

startchar2:

LINE (px%, py%)-(px% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, py% + eheight(chartype%) * charpt% * ptmm / .25), 2, B
CursorDisplay px%, py%


LINE (pxold%, pyold%)-(pxold% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, pyold% + eheight(chartype%) * charpt% * ptmm / .25), 0, B
LINE (px%, py%)-(px% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, py% + eheight(chartype%) * charpt% * ptmm / .25), 2, B
pxold% = px%: pyold% = py%
CursorDisplay px%, py%
LINE (pxold%, pyold%)-(pxold% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, pyold% + eheight(chartype%) * charpt% * ptmm / .25), 0, B
CursorDisplay px%, py%
IF px% + 10 - pxo% > pxmax% OR py% + 16 - pyo% > pymax% THEN GOTO donechar2
xx(nobj%, 0) = px%: yy(nobj%, 0) = py%
L.Text px%, py%: ams$ = "": PRINT "-> "; : Chr.Input ams$
L.Text px%, py%: PRINT SPACE$(LEN(ams$) + 3);
IF ams$ = "" THEN GOTO donechar2
obj%(nobj%, 0) = 10: obj%(nobj%, 1) = LEN(ams$)
obj%(nobj%, 2) = 0: obj%(nobj%, 3) = -1: obj%(nobj%, 4) = charpt%
obj%(nobj%, 5) = chartype%

'Put object number of Box + 1, i.e. string number in Obj(x,6)
obj%(nobj%, 6) = nobj%

G.Charset ams$, nobj%
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
'
donechar2:
SetInst job%
KeySwitch 0
'Fixing the bug of boxtext job=0---> job=4
job% = 4
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 68: COLOR 3: PRINT kky$(9); : COLOR 7

CursorDisplay ipx%, ipy%


' end box text section

GOTO startbox:
'
donebox:
SetInst job%
KeySwitch 1
job% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
wx1% = 31 * 8 - 8
wx2% = 31 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 31: COLOR 3: PRINT kky$(5); : COLOR 7
CL.R.edraw 0, 0
'
END SUB

SUB G.Char
'                                                                     string
job% = 5
KeySwitch 0
SetInst job%
wx1% = 68 * 8 - 8
wx2% = 68 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(9), 0, 1
'
startchar:
pxold% = px%: pyold% = py%
CursorDisplay px%, py%
LINE (px%, py%)-(px% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, py% + eheight(chartype%) * charpt% * ptmm / .25), 2, B
CursorDisplay px%, py%
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 LINE (pxold%, pyold%)-(pxold% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, pyold% + eheight(chartype%) * charpt% * ptmm / .25), 0, B
 LINE (px%, py%)-(px% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, py% + eheight(chartype%) * charpt% * ptmm / .25), 2, B
 pxold% = px%: pyold% = py%
 CursorDisplay px%, py%
LOOP UNTIL keyin% <> 1
VIEW SCREEN (0, 0)-(windowx%(0), winpy%)
CursorDisplay px%, py%
LINE (pxold%, pyold%)-(pxold% + epitch%(chartype%, 0) * charpt% / 250 * ptmm, pyold% + eheight(chartype%) * charpt% * ptmm / .25), 0, B
CursorDisplay px%, py%
IF keyin% = 4 THEN GOTO donechar
'IF keyin% = 3 THEN G.CharDisp: GOTO startchar
IF px% + 10 - pxo% > pxmax% OR py% + 16 - pyo% > pymax% THEN GOTO donechar
xx(nobj%, 0) = px%: yy(nobj%, 0) = py%
L.Text px%, py%: ams$ = "": PRINT "-> "; : Chr.Input ams$
L.Text px%, py%: PRINT SPACE$(LEN(ams$) + 3);
IF ams$ = "" THEN GOTO startchar
obj%(nobj%, 0) = 10: obj%(nobj%, 1) = LEN(ams$)
obj%(nobj%, 2) = 0: obj%(nobj%, 3) = -1: obj%(nobj%, 4) = charpt%
obj%(nobj%, 5) = chartype%: obj%(nobj%, 6) = 0
G.Charset ams$, nobj%
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
GOTO startchar
'
donechar:
SetInst job%
KeySwitch 1
job% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 68: COLOR 3: PRINT kky$(9); : COLOR 7
'
END SUB

SUB G.CharDisp
'                                           character font selection display
ipy% = py%: ipx% = px%
L.Text ipx%, ipy%
charptold% = charpt%: a$ = fno$(charpt%, 1)
PRINT "Size (10 or 12 pt.) = "; : Chr.Input a$
charpt% = VAL(a$)
IF charpt% = 0 OR (charpt% <> 10 AND charpt% <> 12) THEN charpt% = charptold%
L.Text ipx%, ipy%: PRINT SPACE$(28);
DO
 L.Text ipx%, ipy%
 PRINT "Font= "; chartype$(chartype%)  '; ".";
 CursorMotion keyin%
 IF keyin% = 2 THEN
       chartype% = chartype% + 1: IF chartype% > UBOUND(chartype$) THEN chartype% = 0
 END IF
LOOP UNTIL keyin% = 3
L.Text ipx%, ipy%
PRINT SPACE$(5)
L.Text ipx%, ipy%
PRINT "'"; chartype$(chartype%); "' character in "; charpt%; "pt.";
SLEEP 1: L.Text ipx%, ipy%
PRINT SPACE$(5); SPACE$(10); SPACE$(25);
'
END SUB

SUB G.Charset (ams$, n%)
'                                               character code decomposition
FOR i% = 1 TO LEN(ams$): a$ = MID$(ams$, i%, 1): j% = LEN(a$)
IF j% = 1 THEN
 yy(n%, i%) = 0!: xx(n%, i%) = ASC(a$)
ELSE
 a$ = STR$(ASC(a$))
 yy(n%, i%) = VAL("&H" + LEFT$(a$, 2))
 xx(n%, i%) = VAL("&H" + RIGHT$(a$, 2))
END IF
NEXT i%
'
END SUB

SUB G.Crcl
'                                                                     circle
'LOCATE line3%, 42: PRINT "filler pattern"
xx(nobj%, 0) = px%: yy(nobj%, 0) = py%
sx% = px%: sy% = py%: rold = 1
'fill% = 0
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 CIRCLE (sx%, sy%), rold, 0, , , 1
 IF keyin% = 4 THEN CursorDisplay px%, py%: GOTO donecrcl
 rad = SQR((px% - sx%) ^ 2 + (py% - sy%) ^ 2)
 CIRCLE (sx%, sy%), rad, 2, , , 1
'***********
'For fillpattern for circle
'
'  IF fill% = 0 THEN
'        PAINT ((sx% + px%) / 2, (sy% + py%) / 2), 0, 2
'  ELSE
'        PAINT ((sx% + px%) / 2, (sy% + py%) / 2), tlp$(fill%), 2
'  END IF
'**************
 rold = rad
 CursorDisplay px%, py%
LOOP UNTIL keyin% = 2
CursorDisplay px%, py%
CIRCLE (sx%, sy%), rad, 0, , , 1
CursorDisplay px%, py%
xx(nobj%, 1) = px%: yy(nobj%, 1) = py%: xx(nobj%, 2) = rad
obj%(nobj%, 0) = 5: obj%(nobj%, 1) = 2
obj%(nobj%, 2) = 1: obj%(nobj%, 3) = -1
obj%(nobj%, 4) = thick%: obj%(nobj%, 5) = 0
obj%(nobj%, 6) = 0
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
'
donecrcl:
'
END SUB

SUB G.Crcl.Ellps
'                                                              circle+ellpse
job% = 2
KeySwitch 0
SetInst job%
wx1% = 17 * 8 - 8
wx2% = 17 * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(3), 0, 1
'
startcrclellps:
DO
 CursorMotion keyin%
LOOP UNTIL keyin% <> 1
VIEW SCREEN (0, 0)-(windowx%(0), winpy%)
SELECT CASE keyin%
 CASE 2
       G.Crcl
 CASE 3
       G.Ellps
 CASE 4
       GOTO donecrclellps
END SELECT
GOTO startcrclellps
'
donecrclellps:
SetInst job%
KeySwitch 1
job% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1% - 1, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, 17: COLOR 3: PRINT kky$(3); : COLOR 7
'
END SUB

SUB G.Curve (curve%, closed%)
'                                                      straight/curved lines
job% = 1
KeySwitch 0
SetInst job%
wx1% = (curve% * 7 - 4 + closed% * 44) * 8 - 8
wx2% = (curve% * 7 - 4 + closed% * 44) * 8 + 40
wy1% = line2% * texth% - texth%
wy2% = line2% * texth%
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(curve% + 5 * closed%), 0, 1
'
startcurve:
node% = 0: nodeismax% = 0
DO
 CursorMotion keyin%
LOOP UNTIL keyin% <> 1
IF keyin% >= 3 THEN GOTO donest
pxold% = px%: pyold% = py%
xx(nobj%, 0) = px%: yy(nobj%, 0) = py%
DO
sx% = px%: sy% = py%
node% = node% + 1
IF node% + closed% + curve% - 1 = UBOUND(xx, 2) THEN nodeismax% = 1
 DO
       CursorMotion keyin%
       CursorDisplay px%, py%
       IF wnode% <> 0 AND node% > 1 THEN
          PSET (xx(nobj%, 0), yy(nobj%, 0)), 7
          FOR i% = 1 TO (node% - 1)
             LINE -(xx(nobj%, i%), yy(nobj%, i%)), 7
          NEXT i%
       END IF
       wnode% = 0
       LINE (sx%, sy%)-(pxold%, pyold%), 0
       LINE (sx%, sy%)-(px%, py%), 7
       pxold% = px%: pyold% = py%
       CursorDisplay px%, py%
 LOOP UNTIL keyin% <> 1
 CursorDisplay px%, py%
 LINE (sx%, sy%)-(px%, py%), 7
 CursorDisplay px%, py%
 xx(nobj%, node%) = px%: yy(nobj%, node%) = py%
 IF keyin% = 4 THEN EXIT DO
 IF nodeismax% = 1 THEN keyin% = 3
LOOP UNTIL keyin% = 3 AND node% >= 1 + closed%
IF curve% = 1 THEN
 obj%(nobj%, 0) = 1
ELSE
 obj%(nobj%, 0) = 3
END IF
obj%(nobj%, 1) = node%
obj%(nobj%, 2) = node% - closed%: obj%(nobj%, 3) = node% - closed%
obj%(nobj%, 4) = thick%: obj%(nobj%, 5) = ltype%: obj%(nobj%, 6) = 0
CursorDisplay px%, py%
PSET (xx(nobj%, 0), yy(nobj%, 0)), 0
FOR i% = 1 TO node%: LINE -(xx(nobj%, i%), yy(nobj%, i%)), 0: NEXT i%
CursorDisplay px%, py%
IF keyin% = 4 THEN GOTO donest
IF closed% <> 0 THEN
 FOR i% = 0 TO 3: obj%(nobj%, i%) = obj%(nobj%, i%) + 1: NEXT i%
 node% = node% + 1
 xx(nobj%, node%) = xx(nobj%, 0): yy(nobj%, node%) = yy(nobj%, 0)
END IF
IF curve% = 2 AND INT(node% / 2) * 2 <> node% THEN G.Addnode nobj%, node%, 0
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
GOTO startcurve
'
donest:
SetInst job%
KeySwitch 1
job% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line2%, curve% * 7 - 4 + closed% * 44: COLOR 3
PRINT kky$(curve% + 5 * closed%); : COLOR 7
'
END SUB

SUB G.Ellps
'                                                                    ellipse
rold = 1: rtold = 1:
sx% = px%: sy% = py%: cx% = px%: cy% = py%
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 CIRCLE (cx%, cy%), rold, 0, , , rtold
 IF keyin% = 4 THEN CursorDisplay px%, py%: GOTO donellps
 cx% = (px% + sx%) / 2!: cy% = (py% + sy%) / 2!
 rad = ABS(px% - sx%) / 2!: rt = ABS(py% - sy%) / 2!
 IF rad = 0! OR rt = 0! THEN
       rad = 0!: rt = 1!
 ELSE
       rt = rt / rad
       IF rt > 1! THEN rad = rt * rad
 END IF
 CIRCLE (cx%, cy%), rad, 2, , , rt
 '***********
 'For fillpattern for circle
 '
 '  IF fill% = 0 THEN
 '      PAINT ((sx% + px%) / 2, (sy% + py%) / 2), 0, 2
 '  ELSE
 '      PAINT ((sx% + px%) / 2, (sy% + py%) / 2), tlp$(fill%), 2
 '  END IF
 '**************

 rold = rad: rtold = rt
 CursorDisplay px%, py%
LOOP UNTIL keyin% = 3
CursorDisplay px%, py%
CIRCLE (cx%, cy%), rad, 0, , , rt
CursorDisplay px%, py%
xx(nobj%, 0) = cx%: yy(nobj%, 0) = cy%: xx(nobj%, 2) = rad
xx(nobj%, 1) = cx%: yy(nobj%, 1) = cy%: yy(nobj%, 2) = rt
IF rt < 1! THEN
 xx(nobj%, 1) = cx% + rad
ELSE
 yy(nobj%, 1) = cy% - rad
END IF
obj%(nobj%, 0) = 7: obj%(nobj%, 1) = 2: obj%(nobj%, 2) = 1
obj%(nobj%, 3) = -1: obj%(nobj%, 4) = thick%: obj%(nobj%, 5) = 0
obj%(nobj%, 6) = 0
CursorDisplay px%, py%
SetObject nobj%, 7, 0
CursorDisplay px%, py%
nobj% = nobj% + 1
Object.Max.Check
'
donellps:
'
END SUB

SUB G.XYparam (x0%, y0%, x1%, y1%, x2%, y2%, ax, bx, cx, ay, by, cy)
'                                    parametric parabolic curve coefficients
ax = -(-x0% + 2! * x1% - x2%) / 2!
bx = -(3! * x0% - 4! * x1% + x2%) / 2!
cx = x0%
ay = -(-y0% + 2! * y1% - y2%) / 2!
by = -(3! * y0% - 4! * y1% + y2%) / 2!
cy = y0%
'
END SUB

SUB L.Text (ipx%, ipy%)
'                                                      locate on text screen
jpx% = INT(CSNG(ipx% - pxo%) / wndwxy(wndwfctr%) / 8!) + 2
jpy% = INT(CSNG(ipy% - pyo%) / wndwxy(wndwfctr%) / 16!) + 2
IF jpy% > 22 THEN jpy% = jpy% - 3
LOCATE jpy%, jpx%
'
END SUB

SUB MaxMin (ppxx%, ppyy%)
'                                                        set maximum/minimum
IF ppxx% < xmin% THEN xmin% = ppxx%
IF ppxx% > xmax% THEN xmax% = ppxx%
IF ppyy% < ymin% THEN ymin% = ppyy%
IF ppyy% > ymax% THEN ymax% = ppyy%
'
END SUB

SUB MoveObj (c%)
'                                                       move or copy objects
job% = 7
KeySwitch 0
SetInst job%
wx1% = (3 + 7 * c%) * 8 - 8
wx2% = (3 + 7 * c%) * 8 + 40
wy1% = line1% * texth% - texth%
wy2% = line1% * texth%
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 11, BF
ptext PMAP(wx1%, 2) + 19, PMAP(wy1%, 3) + 1, kky$(11 + c%), 0, 1
'
startmovecopy:
Marking 1, n%
selh% = 1
IF n% = 0 THEN Marking 1, n%: GOTO donemovecopy
DO
 CursorMotion keyin%
LOOP UNTIL keyin% <> 1
VIEW SCREEN (0, 0)-(windowx%(0), winpy%)
woldrad% = 0
SELECT CASE keyin%
 CASE 2
       selh% = 0
       MoveObject 1, c%
  CASE 3
       MoveObject 0, c%
 CASE ELSE
       Marking 1, n%
END SELECT
woldrad% = 0
IF keyin% <> 4 THEN GOTO startmovecopy
'
donemovecopy:
SetInst job%
KeySwitch 1
job% = 0
selh% = 0
VIEW SCREEN (0, 0)-(windowx%(0), windowy%(0))
LINE (PMAP(wx1%, 2), PMAP(wy1%, 3))-(PMAP(wx2%, 2), PMAP(wy2%, 3)), 0, BF
LOCATE line1%, 3 + 7 * c%: COLOR 3: PRINT kky$(11 + c%); : COLOR 7
'
END SUB

SUB MoveObject (total%, c%)
'                                                      really moving objects
sx% = px%: sy% = py%: pxold% = px%: pyold% = py%
IF total% = 1 THEN
 total% = 0
 Marking.Chk 1, mobj%(total%), snode%
 IF mobj%(total%) < 0 THEN Marking 1, n%: EXIT SUB
ELSE
 DO
       CursorMotion keyin%
       CursorDisplay px%, py%
       LINE (sx%, sy%)-(pxold%, pyold%), 0, B
       IF keyin% = 4 THEN CursorDisplay px%, py%: Marking 1, n%: EXIT SUB
       LINE (sx%, sy%)-(px%, py%), 2, B
       CursorDisplay px%, py%
       pxold% = px%: pyold% = py%
 LOOP UNTIL keyin% = 3
 selh% = 0
 CursorDisplay px%, py%
 LINE (sx%, sy%)-(px%, py%), 0, B
 CursorDisplay px%, py%
 Marking.Reg sx%, sy%, px%, py%, total%
 IF total% < 0 THEN Marking 1, n%: EXIT SUB
END IF
IF total% > UBOUND(mobj%) OR nobj% + total% > UBOUND(obj%, 1) THEN GOTO no.way.to.move
'                                                                group check
gtotal% = 0
FOR k% = 0 TO total%
IF fnoo%(mobj%(k%)) = obj%(mobj%(k%), 0) THEN GOTO movegroup2
ggroup% = obj%(mobj%(k%), 0) - fnoo%(mobj%(k%))
FOR i% = 0 TO nobj% - 1
IF fnoo%(i%) = obj%(i%, 0) THEN GOTO movegroup1
FOR j% = 0 TO total%
IF i% = mobj%(j%) THEN GOTO movegroup1
NEXT j%
IF obj%(i%, 0) - fnoo%(i%) = ggroup% THEN
 gtotal% = gtotal% + 1
 IF total% + gtotal% > UBOUND(mobj%) THEN GOTO no.way.to.move
 IF nobj% + total% + gtotal% > UBOUND(obj%, 1) THEN GOTO no.way.to.move
 mobj%(total% + gtotal%) = i%
END IF
movegroup1:
NEXT i%
movegroup2:
NEXT k%
total% = total% + gtotal%
Marking 1, n%
'
FOR i% = 0 TO total%
FOR j% = 0 TO 6: obj%(nobj% + i%, j%) = obj%(mobj%(i%), j%): NEXT j%
FOR j% = 0 TO obj%(mobj%(i%), 1)
xx(nobj% + i%, j%) = xx(mobj%(i%), j%)
yy(nobj% + i%, j%) = yy(mobj%(i%), j%)
NEXT j%: NEXT i%: dx% = 0: dy% = 0
'
DO
 CursorMotion keyin%
 CursorDisplay px%, py%
 IF keyin% = 4 THEN
       FOR i% = 0 TO total%: wkill% = 1: SetObject nobj% + i%, 0, 1: NEXT i%
       GOTO mvobj
 END IF
 ddx% = px% - pxold%: ddy% = py% - pyold%
 dx% = dx% + ddx%: dy% = dy% + ddy%
 a$ = KeyIsTouched$                        'check continuous motion, silly?
 IF (mouswitch% = 0 AND a$ = "") OR (mouswitch% AND a$ = "" AND row% = py% AND col% = px%) THEN
       IF c% = 0 OR dx% <> 0 OR dy% <> 0 THEN
         FOR i% = 0 TO total%: wkill% = 1: SetObject nobj% + i%, 0, 1: NEXT i%
       END IF
       FOR i% = 0 TO total%: jlast% = obj%(nobj% + i%, 2)
       IF fnoo%(nobj% + i%) = 2 OR fnoo%(nobj% + i%) = 4 THEN jlast% = jlast% + 1
       FOR j% = 0 TO jlast%
       xx(nobj% + i%, j%) = xx(nobj% + i%, j%) + dx%
       yy(nobj% + i%, j%) = yy(nobj% + i%, j%) + dy%: NEXT j%
       SetObject nobj% + i%, 3, 1
       NEXT i%
       dx% = 0: dy% = 0
 END IF
 CursorDisplay px%, py%
 pxold% = px%: pyold% = py%
LOOP UNTIL keyin% = 2 OR keyin% = 3
'
CursorDisplay px%, py%
FOR i% = 0 TO total%: SetObject nobj% + i%, 0, 1: NEXT i%
groupchk% = 0
IF c% = 0 THEN
 FOR i% = 0 TO total%: SetObject mobj%(i%), 0, 0: NEXT i%
 FOR i% = 0 TO total%
 FOR j% = 0 TO 6: obj%(mobj%(i%), j%) = obj%(nobj% + i%, j%): NEXT j%
 FOR j% = 0 TO obj%(mobj%(i%), 1): xx(mobj%(i%), j%) = xx(nobj% + i%, j%)
 yy(mobj%(i%), j%) = yy(nobj% + i%, j%): NEXT j%: NEXT i%
 FOR i% = 0 TO total%: FOR j% = 0 TO nobj% - 1
 IF fnoo%(j%) = 11 AND obj%(j%, 5) = mobj%(i%) THEN
       SetObject j%, 0, 0
       G.ArrowDirec obj%(j%, 5), obj%(j%, 6), j%
       SetObject j%, 7, 0
 END IF
 NEXT j%: NEXT i%
ELSE
 arrow% = 0: arrowoverflow% = 0
 FOR i% = 0 TO total%: SetObject nobj% + i%, 7, 0
 IF obj%(nobj% + i%, 0) <> fnoo%(nobj% + i%) THEN
       obj%(nobj% + i%, 0) = 100 * group% + fnoo%(nobj% + i%)
       groupchk% = 1
 ELSE
       obj%(nobj% + i%, 0) = fnoo%(nobj% + i%)
 END IF
 FOR j% = 0 TO nobj% - 1
 IF fnoo%(j%) = 11 AND obj%(j%, 5) = mobj%(i%) THEN
       mmobj% = nobj% + total% + arrow% + 1
       IF mmobj% > UBOUND(obj%, 1) THEN arrowoverflow% = arrowoverflow% + 1
       IF arrowoverflow% = 0 THEN
         FOR k% = 0 TO 6: obj%(mmobj%, k%) = obj%(j%, k%): NEXT k%
         IF obj%(mmobj%, 0) <> fnoo%(mmobj%) THEN
               obj%(mmobj%, 0) = 100 * group% + fnoo%(mmobj%)
         ELSE
               obj%(mmobj%, 0) = fnoo%(mmobj%)
         END IF
         FOR k% = 0 TO obj%(mmobj%, 1): xx(mmobj%, k%) = xx(j%, k%)
         yy(mmobj%, k%) = yy(j%, k%): NEXT k%: obj%(mmobj%, 5) = nobj% + i%
         G.ArrowDirec obj%(mmobj%, 5), obj%(mmobj%, 6), mmobj%
         SetObject mmobj%, 7, 0: arrow% = arrow% + 1
       END IF
 END IF
 NEXT j%: NEXT i%
 IF groupchk% = 1 THEN group% = group% + 1
 nobj% = nobj% + total% + arrow% + 1
 IF arrowoverflow% > 0 THEN
       COLOR 14: LOCATE 2, 25
       PRINT CHR$(7); " "; arrowoverflow%; " arrow(s)  NOT  copied! ";
       COLOR 7
 END IF
END IF
mvobj:
FOR i% = 0 TO total%: SetObject mobj%(i%), 7, 0: NEXT i%
CursorDisplay px%, py%
EXIT SUB
'
no.way.to.move:
Marking 1, n%
COLOR 14: LOCATE 2, 25
PRINT CHR$(7); " No way to move/copy that many... ";
COLOR 7
'
END SUB

SUB PPUT (xp, yp, markp%())
'                                                            conditional PUT
IF xp < pxmax% AND xp > pxmin% AND yp < pymax2% AND yp > pymin% THEN
 PUT (xp, yp), markp%, XOR
END IF
'
END SUB

SUB SetObject (n%, clr%, simple%)
'                                                            set each object
IF fnoo%(n%) < 1 THEN EXIT SUB
ON fnoo%(n%) GOSUB ln, ln, cv, cv, crc, arc, ellps, box, fbox, str, arr
EXIT SUB
'                                                                       line
ln:
FOR i% = 1 TO obj%(n%, 1)
D.Lines INT(xx(n%, i% - 1)), INT(yy(n%, i% - 1)), INT(xx(n%, i%)), INT(yy(n%, i%)), clr%, 0, obj%(n%, 4), obj%(n%, 5), 0, simple%
NEXT i%: RETURN
'                                                                      curve
cv:
IF simple% = 1 THEN GOTO ln
FOR i% = 0 TO obj%(n%, 1) - 2
x0% = xx(n%, i%): x1% = xx(n%, i% + 1): x2% = xx(n%, i% + 2)
y0% = yy(n%, i%): y1% = yy(n%, i% + 1): y2% = yy(n%, i% + 2)
G.XYparam x0%, y0%, x1%, y1%, x2%, y2%, ax, bx, cx, ay, by, cy
jlast% = 4: IF i% = obj%(n%, 1) - 2 THEN jlast% = 9
FOR j% = 0 TO jlast%
t = j% / 5!: sx% = ax * t * t + bx * t + cx: sy% = ay * t * t + by * t + cy
t = (j% + 1) / 5!: ex% = ax * t * t + bx * t + cx: ey% = ay * t * t + by * t + cy
D.Lines sx%, sy%, ex%, ey%, clr%, 0, obj%(n%, 4), obj%(n%, 5), 0, simple%
NEXT j%: NEXT i%
RETURN
'                                                                     circle
crc:
D.Circles INT(xx(n%, 0)), INT(yy(n%, 0)), xx(n%, 2), -1, -1, 0, clr%, obj%(n%, 4), simple%, obj%(n%, 6)
RETURN
'                                                                        arc
arc:
D.Circles INT(xx(n%, 1)), INT(yy(n%, 1)), xx(n%, 3), -1, yy(n%, 3), yy(n%, 4), clr%, obj%(n%, 4), simple%, obj%(n%, 6)
RETURN
'                                                                    ellipse
ellps:
D.Circles INT(xx(n%, 0)), INT(yy(n%, 0)), xx(n%, 2), yy(n%, 2), -1, 0, clr%, obj%(n%, 4), simple%, obj%(n%, 6)
RETURN
'                                                                        box
box:
D.Lines INT(xx(n%, 0)), INT(yy(n%, 0)), INT(xx(n%, 1)), INT(yy(n%, 1)), clr%, 1, obj%(n%, 4), obj%(n%, 5), 0, simple%
RETURN
'                                                                 filled box
fbox:
D.Lines INT(xx(n%, 0)), INT(yy(n%, 0)), INT(xx(n%, 1)), INT(yy(n%, 1)), clr%, 2, obj%(n%, 4), 0, obj%(n%, 6), simple%
RETURN
'                                                                    strings
str:
D.Strings n%, clr%, simple%
RETURN
'                                                                      arrow
arr:
FOR i% = 0 TO 1
D.Lines INT(xx(n%, i%)), INT(yy(n%, i%)), INT(xx(n%, i% + 1)), INT(yy(n%, i% + 1)), clr%, 0, obj%(n%, 4), 0, 0, simple%
NEXT i%
RETURN
'
END SUB