WIDJUP CAD

Products: Winkjet 1
Developer(s): William J. Pedersen
Date: 1989
Type: Program
Platform(s): TS 2068

WIDJUP CAD is a printed-circuit-board artwork program. You describe a board as a data array of up to 99 items: straight lines, boxes, circles and ellipses, 45-degree traces, jogs and slants between two points, round and oblong pads, and quarter-circle arcs. Each item can be repeated in X and Y at a set pitch and can be marked as an eraser that clears what lies under it. The EDIT service shows five items at a time and changes them with number-key commands (ADD, FIX, SELECT, PUT, CUT, MAP, DEL); DISPLAY draws the whole board on a 5 × 4 inch grid; REPORT prints the array. GENERATE turns the board into a 960-dot-wide printer raster at a chosen scale and sends it to an Epson-class dot-matrix printer, to a series of 4 KB image frames on disk, or both, and COPY prints saved frames as 2× photo masters for etching.

The program is by William J. Pedersen of The WIDJUP Co., who sold it as shareware: CAD#2 for the Olivetti PR2300 ink-jet printer, CAD#3 for Epson-class 9-pin printers on the Larken disk system (©1989), and CAD#5, the Oliger JLO SAFE version (©1991). UPDATE magazine printed the program and manual in April 1992 and the CAD#5 listings in October 1992. This download has CAD#5 as the main program and CAD#3 alongside it, both converted to load from tape, with the sample data arrays, the 93-frame demo image, the disk documents as text and the two original disk images.

Program Analysis

Loading chain

CAD#5BE lists the current channel table and rebuilds it: PRINT #4 goes to the TS2040 printer, and a new LPRINT #5 / LLIST #5 channel for formatted printing is assembled into memory from DATA lines written as mnemonic variable names (LET CP=254: LET JRZ=40 and so on), the same scheme as Pedersen’s IO with LLIST #5. INTFC_BE then asks which parallel interface is fitted (Tasman A or B, AERCO/Oliger, A&J, or a general Z80 PIO), shows the port and bit values so they can be changed, and pokes a 242-byte printer module to 26995 from DATA lines whose port numbers and relocated addresses are calculated as they are read (DEF FN b() splits each address into its two bytes). CAD_BE loads the UDG code CAD_CU and the printer-window table J$T, installs the module and shows the main menu.

Data arrays and editing

A board is the array z(100,11): row 1 holds the item count, and each later row holds an item type and up to ten parameters (position, size, repeat counts and pitch, eraser flag). The editor redraws a five-item window with PRINT AT and reads single keys with INKEY$; the DISPLAY service plots each item type with PLOT/DRAW and a circle routine on a scaled grid, labelling the item number as it goes.

Generating the raster

GENERATE converts every item to a scanline description in the work array y(100,13) (lines 1200–1302) and then builds the image 24 printer dot-rows at a time. Each 960-dot row is folded across four 256-pixel character rows of the screen, so one frame of the top two-thirds of the display (4096 bytes) holds 24 rows. Lines 210–214 work out which items cross each row and call the item’s own fill routine through a computed GO SUB y(u,1); the printer module then sends the frame as Epson graphics, and frames can be saved for COPY or edited one at a time in the image update service.

Notable Techniques

  • Channel #5 is a real printer channel assembled at run time from DATA mnemonics, so LPRINT #5 and LLIST #5 give formatted output.
  • The printer module is relocatable: DEF FN b(b,o) computes the low or high byte of each absolute address as the DATA is read.
  • Program-wide constants are held in short variables (i, ii, iii, iv, six, z) to save memory and time, and menu choices are dispatched with GO SUB SR+xx*n.
  • Item types are drawn by computed GO SUB to the line number stored in the work array.

Potential Issues

  • In CAD#5, GENERATE “Update” looks for frame 1 with a .CZ suffix (line 3146, and the image copy service at 8106), although CAD#5 saves frames without it, so an existing image could not be found.
  • In CAD#5, line 208 repeats the frame step of line 206 and loads a second frame, so Update mode skips every other frame. CAD#3 steps once per pass.
  • The DEM frames on the Oliger CAD#5 demo disks are catalogued with load address 16834 instead of 16384, so they load 450 bytes low and print incorrectly; the CAD#3 demo frames in this download are the Larken set, which load correctly.
  • Line 1 of CAD#5 sets ON ERR GO TO 9885, a line that does not exist.

Both programs came from Larken and Oliger disks of Pedersen’s and were converted to run from tape: the disk prefixes, drive selects and CAT commands were removed, the DIRECTORY service (which read the floppy controller ports directly) now says it is not available, the interface builder leaves its module in memory instead of saving it to disk, and the two CAD#5 Update bugs above are fixed in the tape version. They were tested in ZEsarUX on a stock TS2068: loading, the interface set-up, loading the DEMO array, DISPLAY, EDIT and GENERATE to the screen work; printing needs a real Centronics interface and printer and was not tested.

Related Products

Lets you use all the features of the Olivetti PR2300 printer. Dump the screen to the printer in normal size or enlarged.

Related Articles

Follow up to earlier article about PCB design program.
Follow up to PCB design programs in prior issues.
Discussion of printer drivers and the challenges of printing graphics to 9 and 24 pin printers.
CAD program and manual for the TS 2068.
Follow up to the PCB development program in the April 1992 issue.

Related Content

Image Gallery

Source Code

    1 ON ERR GO TO 9885: GO TO Main
   12 IF a1>=960 THEN RETURN 
   13 LET a=INT a1: IF a<0 THEN LET a=0
   14 LET b=INT (b1-1): IF a>b THEN RETURN 
   15 IF b>959 THEN LET b=959
   16 LET c=INT (a/256): LET a=a-256*c: LET d=INT (b/256): LET b=b-256*d: LET s=f-8*c: LET d=d-c
   17 IF NOT d THEN PLOT a,s: DRAW b-a,0: RETURN 
   18 PLOT a,s: DRAW 255-a,0: LET s=s-8
   19 IF d=3 THEN PLOT 0,s: DRAW 255,0: LET s=s-8
   20 IF d>=2 THEN PLOT 0,s: DRAW 255,0: LET s=s-8
   21 PLOT 0,s: DRAW b,0: RETURN 
   23 STOP 
   44 LET j=z(kk+1,7)
   45 GO SUB 12: IF j<2 THEN RETURN 
   46 LET j=j-1: LET A1=A1+y(kk,8): LET B1=B1+y(kk,8): GO TO 45
  100 IF y>y(kk,5) THEN GO TO 201
  101 LET a1=y(kk,2): LET b1=y(kk,3): GO TO 44
  120 IF y>y(kk,5) THEN GO TO 201
  121 LET a=(y(kk,5)+y(kk,6))/2: LET c=y(kk,4): LET b=y(kk,13): LET s=b+y(kk,12)*(y-a): LET a1=s-c: LET b1=s+c: GO TO 44
  130 IF y>y(kk,5) THEN GO TO 201
  131 LET d=y(kk,2): LET j=y(kk,3): LET c=y(kk,4): LET a=(y(kk,5)+y(kk,6))/2: LET b=y(kk,13)
  132 LET s=b+y(kk,12)*(y-a)
  133 LET a1=s-c: IF a1<d THEN LET a1=d
  134 LET b1=s+c: IF b1>j THEN LET b1=j
  135 GO TO 44
  140 LET b=(y(kk,5)+y(kk,6))/2: LET c=y(kk,4): LET d=y-b: LET s=(1-d*d/c/c): IF y>y(kk,5) OR s<z THEN GO TO 201
  141 LET a=y(kk,13): LET s=c*k1*SQR s: LET a1=a-s: LET b1=a+s: GO TO 44
  150 LET b=(y(kk,5)+y(kk,6))/2: LET c=y(kk,4): LET d=y-b: LET s=(1-d*d/c/c): IF y>y(kk,5) OR s<z THEN GO TO 201
  151 LET a=y(kk,13): LET s=c*k1*SQR s: IF s>y(kk,12) THEN LET s=y(kk,12)
  152 LET a1=a-s: LET b1=a+s: GO TO 44
  160 LET b=(y(kk,5)+y(kk,6))/2: LET c=y(kk,4): LET d=y-b: LET s=(1-d*d/c/c): IF y>y(kk,5) OR s<z THEN GO TO 201
  161 LET s=c*y(kk,3)*SQR s
  162 LET a=y(kk,13): LET a1=a-s: LET b1=a+s: GO TO 44
  170 LET c=y(kk,4): LET d=y-y(kk,6)-y(kk,12): LET s=i-d*d/c/c: IF y>y(kk,5) OR s<z THEN GO TO 201
  172 LET s=c*y(kk,3)*SQR s
  173 LET a=y(kk,13): LET a1=a-(s AND y(kk,2)>3): LET b1=a+(s AND (y(kk,2)<5)): GO TO 44
  201 LET Del=y(kk,10): LET y(kk,5)=y(kk,5)+Del: LET y(kk,6)=y(kk,6)+Del: LET y(kk,9)=y(kk,9)-1: RETURN 
  205 GO SUB 225: LET t=INT ((ff/24) AND Uflag): LET y=24*t-i: LET kk=z
  206 GO SUB 225: LET t=t+i: IF NOT Uflag THEN GO TO 209
  207 LET h$=f$( TO iii)+STR$ t: LOAD h$ CODE 
  208 REM tape version: second frame step removed (it skipped every other frame in Update)
  209 FOR L=z TO 23: LET y=y+i: IF y<ff THEN GO TO 214
  210 LET f=175-32*L+95*INT (L/3): LET u=0: LET kk=0
  211 LET u=u+1: IF y(u,9) THEN IF y>y(u,6) THEN LET kk=u: INVERSE y(u,11): GO SUB y(u,1)
  212 IF u<Last THEN GO TO 211
  213 IF NOT kk THEN GO SUB 225
  214 NEXT L: INVERSE z
  215 IF Gmode=ii OR Gmode=iv THEN GO SUB 454: GO SUB 455: GO SUB 456
  216 REM tape version: no disk-full prompt
  217 IF Gmode>ii THEN LET h$=f$( TO iii)+STR$ t: PRINT AT 15,0;h$;AT 15,16;"Scale=";Scale: SAVE h$ CODE 16384,4112
  218 CLS : PRINT AT 18,ii;f$;"*";scale'" Frame #";t;" done."
  219 LET s=0: FOR n=1 TO Last: LET s=s+y(n,9): NEXT n: IF NOT s THEN LET Uflag=z: RETURN 
  220 GO TO 206
  225 LET ff=4096: LET s=1
  226 IF y(s,9) THEN IF y(s,6)<ff THEN LET ff=y(s,6)
  227 IF s<Last THEN LET s=s+1: GO TO 226
  228 LET ff=ff AND ff>0: RETURN 
  300 FOR n=z(i,i) TO here STEP -i: FOR k=i TO 11: LET z(n+ii,k)=z(n+i,k): NEXT k: NEXT n: LET z(i,i)=z(i,i)+i: RETURN 
  302 FOR n=here TO z(i,i)-i: FOR k=i TO 11: LET z(n+i,k)=z(n+ii,k): NEXT k: NEXT n: LET z(z(i,i)+i,1)=z: LET z(i,i)=z(i,i)-i: IF here>z(i,i) THEN LET here=z(i,i)
  303 RETURN 
  305 PRINT INK 8; PAPER 8;AT ii,11;"LAST ";z(i,i);"  ";AT ii,xx;"SELECT     ";AT ii,27;Here;: FOR k=left TO left+iv: LET b=6*(k-left)+2: LET d=k+1: LET c=(z(d,6)-1) AND (z(d,1)=10): PRINT AT 4,b;k;"  ";AT 5,b;Q$(z(d,1)+1+c);
  306 FOR n=1 TO 11: LET a=INT (z(k+1,n)*1000): PRINT INK 1+(k=Here)+(6 AND k>z(1,1));AT n+6,b;a/1000: NEXT n: NEXT k
  307 PLOT 0,168: DRAW 0,-150: DRAW 254,0: DRAW 0,150: DRAW -254,0: RETURN 
  449 FOR n=i TO 11: POKE (Ld0+CODE o$(n)),CODE j$(Select,n): NEXT n
  450 RANDOMIZE USR (Ld0+CODE o$(12)): RETURN 
  451 LET select=i: GO TO 449
  452 LET select=ii: GO TO 449
  453 LET select=iii: GO TO 449
  454 LET select=iv: GO TO 449
  455 LET select=v: GO TO 449
  456 LET select=six: GO TO 449
 1200 RETURN 
 1210 LET a=z(ss,v)/ii: LET b=(z(ss,iii)+z(ss,iv))/ii: LET c=ABS (b-z(ss,iv))
 1211 LET y(n,i)=LK: LET y(n,ii)=(b-c)*kY: LET y(n,iii)=(b+c)*kY: LET y(n,v)=(z(ss,ii)+a)*kX-i/ii: LET y(n,six)=(z(ss,ii)-a)*kX+i/ii: GO TO rr
 1220 LET b=z(ss,ii): LET c=z(ss,v)/ii: LET a=(z(ss,iii)+z(ss,iv))/ii: LET d=ABS (z(ss,iii)-z(ss,iv))/ii
 1221 LET y(n,i)=LK: LET y(n,ii)=(b-c)*kY: LET y(n,iii)=(b+c)*kY: LET y(n,v)=(a+d)*kX-i/ii: LET y(n,six)=(a-d)*kX+i/ii: GO TO rr
 1230 LET b=z(ss,ii): LET d=z(ss,iv)/ii: LET c=z(ss,v)/ii
 1231 LET y(n,i)=LK: LET y(n,ii)=(b-d)*kY: LET y(n,iii)=(b+d)*kY: LET y(n,v)=(z(ss,iii)+c)*kX-i/ii: LET y(n,six)=(z(ss,iii)-c)*kX+i/ii: GO TO rr
 1240 LET b=z(ss,ii)
 1241 LET y(n,i)=160: LET y(n,iii)=z(ss,v)*k1: LET y(n,iv)=z(ss,iv)*kX: LET y(n,v)=(z(ss,iii)+z(ss,iv))*kX-i/ii: LET y(n,six)=(z(ss,iii)-z(ss,iv))*kX+i/ii: GO TO rr
 1250 LET a=(z(ss,iv)+z(ss,ii))/ii: LET c=(z(ss,iv)-z(ss,ii))/ii: LET d=z(ss,v)/ii: LET b=z(ss,iii)+c*SGN d: LET w=ABS c+ABS d
 1251 LET y(n,i)=130: LET y(n,ii)=(b-w)*kY: LET y(n,iii)=(b+w)*kY: LET y(n,iv)=(ABS d)*kD-i/ii: LET y(n,v)=(a+w)*kX-i/ii: LET y(n,six)=(a-w)*kX+i/ii: LET y(n,12)=k1*SGN d: GO TO rr
 1260 LET a=(z(ss,iv)+z(ss,ii))/ii: LET c=(z(ss,iv)-z(ss,ii))/ii: LET d=z(ss,v)/ii: LET b=z(ss,iii)+c*SGN d: LET w=ABS c+ABS d
 1261 LET y(n,i)=120: LET y(n,ii)=z: LET y(n,iii)=879: LET y(n,iv)=(ABS d*kD)-i/ii: LET y(n,v)=(a+w)*kX-i/ii: LET y(n,six)=(a-w)*kX+i/ii: LET y(n,12)=k1*SGN d: GO TO rr
 1270 LET c=z(ss,ii): LET a1=z(ss,iii): LET d=z(ss,iv): LET b1=z(ss,v): IF c=d OR a1=b1 THEN GO TO 1310
 1271 LET a=(a1+b1)/ii: LET b=(c+d)/ii: LET Tan=(b1-a1)/(d-c): LET d=ABS (d-c)/ii: LET c=ABS (b1-a1)/ii
 1272 LET w=z(ss,six)/ii: LET An=ATN Tan: LET Sin=SIN An: LET ew=ABS (w*Sin): LET eh=w*COS An
 1273 LET y(n,i)=130: LET y(n,ii)=(b-d-ew)*kY: LET y(n,iii)=(b+d+ew)*kY: LET y(n,iv)=ABS (w/Sin*kY)-i/ii: LET y(n,v)=(a+c+eh)*kX-i/ii: LET y(n,six)=(a-c-eh)*kX+i/ii: LET y(n,12)=k1/Tan: GO TO rr
 1280 LET b=z(ss,ii): LET a=z(ss,iii): LET h=z(ss,iv)
 1281 IF h<=z THEN GO TO 1310
 1282 LET y(n,i)=140: LET y(n,iv)=h*kX: LET y(n,v)=(a+.75*h)*kX-i/ii: LET y(n,six)=(a-.75*h)*kX+i/ii: GO TO rr
 1290 LET b=z(ss,ii): LET a=z(ss,iii): LET h=z(ss,iv)
 1291 IF h<=z THEN GO TO 1310
 1292 LET y(n,i)=150: LET y(n,iv)=h*kX: LET y(n,v)=(a+h)*kX-i/ii: LET y(n,six)=(a-h)*kX+i/ii: LET y(n,12)=.75*h*kY: GO TO rr
 1300 LET b=z(ss,ii): LET a=z(ss,iii): LET c=z(ss,iv): LET d=z(ss,v): LET w=z(ss,six): LET a1=(w>i AND w<7): LET b1=w>v OR w<iii
 1301 LET y(n,i)=170: LET y(n,ii)=w-(iv AND w=8): LET y(n,iii)=d*k1: LET y(n,iv)=c*kX: LET y(n,v)=(a+(c AND b1))*kX-(.5 AND b1): LET y(n,six)=(a-(c AND a1))*kX+(.5 AND a1): LET y(n,12)=(c*kX-i/ii) AND a1
 1302 LET y(n,7)=z(ss,7): LET y(n,8)=z(ss,8)*kY: LET y(n,9)=z(ss,9): LET y(n,10)=z(ss,10)*kX: LET y(n,11)=z(ss,11): LET y(n,13)=b*kY: RETURN 
 1310 PRINT AT 10,iii;" BAD DATA. ITEM #";ss-i;" ";: PAUSE z: ON ERR GO TO Main: LET n=n/z
 3020 CLS : PRINT "    WIDJUP DATA LOAD SERVICE    ";AT 4,1;"DATA ARRAYS are named with _Z.";AT 6,1;"Type the name without _Z, then";AT 7,1;"start the tape.  ENTER to quit."
 3021 REM  removed (LKDOS-only)
 3022 REM  removed (LKDOS-only)
 3023 REM  was Oliger-only
 3024 INPUT "Which(or ENTER)? ";I$: IF LEN I$=z THEN RETURN 
 3028 LET F$=I$+"_Z": LOAD F$ DATA z()
 3029 LET here=1: RETURN 
 3041 IF z(i,i)=z THEN GO TO 3060
 3042 CLS : PRINT AT 8,8;" WARNING  "''" File ";f$;" is present."''" Continuing will destroy file.": INPUT "Continue? Y/n ";I$: IF I$="Y" OR I$="y" THEN DIM z(100,11): LET f$="No Data": GO TO 3060 
 3043 PRINT ''" CANCELLED": RETURN 
 3060 LET here=here-(here AND f$="No Data"): LET q$=" abcdXxijkmnopqrstu"
 3061 GO SUB SE: GO TO HK
 3063 INVERSE p5: PLOT p1,p2: DRAW p3,p4: INVERSE z: RETURN 
 3064 PLOT p1,p2: DRAW p3,z: DRAW z,p4: DRAW -p3,z: DRAW z,-p4: RETURN 
 3065 CIRCLE p1,p2,p3: RETURN 
 3066 PLOT p1,p2: DRAW p3,p4: RETURN 
 3067 PLOT p1,p2: DRAW i,iii: DRAW i,-iii: DRAW -i,-iii: DRAW -i,iii: RETURN 
 3068 PLOT p1,p2: DRAW iii,i: DRAW iii,-i: DRAW -iii,-i: DRAW -iii,i: RETURN 
 3069 LET c=PI/ii: LET a=INT ((p7-1)/ii): LET b=INT (p7/ii)+i: FOR k=a*c TO b*c STEP 1/p3: PLOT p1+p3*COS k,p2+p3*SIN k: NEXT k: RETURN 
 3081 GO SUB 4010: FOR n=i TO LEN f$: PRINT PAPER 5;AT n,i;f$(n);: NEXT n: PRINT AT 20,0;: FOR n=ii TO z(i,i)+i: PRINT AT 18,z;"#";n-i;: LET a=z(n,i)
 3082 IF a=z THEN PRINT AT 11,5; OVER i;" BAD or NO DATA "
 3083 IF a=i THEN LET p1=L*z(n,ii)+xo: LET p2=L*z(n,iii)+yo: LET p3=z: LET p4=L*(z(n,4)-z(n,iii)): LET p5=z(n,11): LET bb=3063
 3084 IF a=ii THEN LET p1=L*z(n,iii)+xo: LET p2=L*z(n,ii)+yo: LET p3=L*(z(n,4)-z(n,iii)): LET p4=z: LET p5=z(n,11): LET bb=3063
 3085 IF a=iii THEN LET p2=L*z(n,ii): LET p1=L*z(n,iii): LET p4=L*z(n,4): LET p3=L*z(n,5): LET p2=p2-p4/ii+yo: LET p1=p1-p3/ii+xo: LET bb=3064
 3086 IF a=iv THEN LET p1=L*z(n,iii)+xo: LET p2=L*z(n,ii)+yo: LET p3=L*z(n,4): LET bb=3065
 3087 IF a=v OR a=six THEN LET p1=L*z(n,ii)+xo: LET p2=L*z(n,iii)+yo: LET p3=L*(z(n,4)-z(n,ii)): LET p4=SGN z(n,5)*p3: LET bb=3066
 3088 IF a=7 THEN LET p4=L*(z(n,4)-z(n,ii)): LET p3=L*(z(n,5)-z(n,iii)): LET p1=L*z(n,iii)+xo: LET p2=L*z(n,ii)+yo: LET bb=3066
 3089 IF a=8 THEN LET p1=L*z(n,iii)-i+xo: LET p2=L*z(n,ii)+yo: LET bb=3067
 3090 IF a=9 THEN LET p1=L*z(n,iii)-iii+xo: LET p2=L*z(n,ii)+yo: LET bb=3068
 3091 IF a=10 THEN LET p1=L*z(n,iii)+xo: LET p2=L*z(n,ii)+yo: LET p3=L*z(n,4): LET p7=z(n,6): LET bb=3069
 3092 LET yy=p2: LET b2=z(n,7): LET a2=z(n,9): LET a3=b2
 3093 ON ERR GO TO 3095: GO SUB bb: LET p2=p2+L*z(n,8): IF b2>1 THEN LET b2=b2-1: GO TO 3093
 3094 LET p2=yy: LET b2=a3: LET p1=p1+L*z(n,10): IF a2>1 THEN LET a2=a2-1: GO TO 3093
 3095 ON ERR RESET : NEXT n: RETURN 
 3100 CLS : PRINT AT 8,2;"WIDJUP DIRECTORY SERVICE";AT 10,2;"needs a disk drive and is not";AT 11,2;"available in the tape version.": RETURN 
 3101 REM  removed (LKDOS-only)
 3102 REM  removed (LKDOS-only)
 3103 REM  removed (LKDOS-only)
 3104 REM  removed (LKDOS-only)
 3105 REM  removed (LKDOS-only)
 3107 REM  removed (LKDOS-only)
 3108 REM  removed (LKDOS-only)
 3109 REM  removed (LKDOS-only)
 3110 REM  removed (LKDOS-only)
 3118 REM  removed (LKDOS-only)
 3119 REM  removed (LKDOS-only)
 3120 INPUT "Comment, Date? ";a$: LPRINT #5'"DATA REPORT.. ";a$;;: LPRINT "lN";CHR$ 6;CHR$ 10
 3121 GO SUB 3080: GO SUB 451: LPRINT CHR$ 10
 3122 LET Last=Z(i,i): FOR l=ii TO Last+i: PRINT AT 19,z,,,,AT 19,z;: LET c=l-1: PRINT " " AND c<lk;" " AND c<10;c;" ";: RESTORE z(l,i)+3200: READ i$: PRINT INVERSE z(l,11);" ";I$;" ";: PRINT " ";: READ k: FOR k=ii TO k+i: READ I$: PRINT I$;: PRINT z(l,k);: NEXT k: GO SUB 3129
 3123 PRINT TAB 14;"[x,y][";z(l,9);"*";z(l,7);"][";z(l,10);";";z(l,8);"]": GO SUB 3129
 3125 NEXT l: PRINT "END OF DATA",,,,: GO SUB 3129: LPRINT "lO";CHR$ 12;: RETURN 
 3128 REM PRINT " " AND c<LK;" " AND c<10;c;"  ";: RETURN 
 3129 GO SUB 453: PRINT AT 19,z,,,,AT 19,z;: RETURN 
 3140 ON ERR RESET : CLS : PRINT "    WIDJUP GENERATE SERVICE     "''"  0   QUIT "''"  1  Screen Only"''"  2  LPRINT"''"  3  FILE"''"  4  LPRINT & FILE"
 3141 INPUT "Select by # ";I$: ON ERR GO TO 3140: LET Gmode=VAL ("0"+I$): ON ERR RESET : IF Gmode<z OR Gmode>iv THEN GO TO 3141
 3142 PRINT '"   Mode is #";Gmode''"  0.556 Scale will print an"'" overlay matching the REPORT."
 3143 IF NOT gmode THEN PRINT ''"CANCELLED": RETURN 
 3144 DIM y(100,13): LET Uflag=z: IF gmode>ii THEN INPUT "New or Update? ";I$: IF LEN I$ THEN IF I$( TO i)="U" OR I$( TO i)="u" THEN LET Uflag=i
 3145 IF NOT Uflag THEN INPUT "SCALE? ";Scale: GO TO 3148
 3146 LET i$=f$( TO iii)+"1": LOAD i$CODE 
 3147 LET i$="": FOR n=22 TO 28: LET i$=i$+SCREEN$ (15,n): NEXT n: LET Scale=VAL i$
 3148 LET kY=Scale*120: LET kX=kY/k1: LET kD=kY*1.414: PRINT #1;"      WORKING "
 3149 LET Last=z(i,i): FOR n=i TO Last: LET ss=n+i: LET nn=z(n+i,i): IF nn<i OR nn>10 OR nn<>INT nn THEN PRINT AT 21,six;"BAD DATA AT ";3000+n;"": STOP : RETURN 
 3150 LET Mode=1200+10*nn: GO SUB Mode: NEXT n: CLS : GO TO 205
 3160 REM " COPY "
 3161 CLS 
 3162 INPUT "FILE(less number)?";I$'"  Count? ";bb: LET I$=I$+"    ": LET I$=I$( TO iii): CLS 
 3163 FOR L=i TO bb: LET H$=I$+STR$ L
 3164 REM tape version: no disk change
 3165 PRINT AT 18,z: LOAD H$ CODE : GO SUB 454: GO SUB 455: GO SUB 456: NEXT L: LPRINT "lN";CHR$ 6;: RETURN 
 3180 ON ERR RESET : CLS : PRINT "      WIDJUP SAVE SERVICE        Existing File is ";F$,""
 3181 PRINT ''" 1  KEEP SAME NAME"'''" 2  RENAME FILE (1-6 CHR$)"'"    (Extension .AZ is provided.)"''" 3  QUIT ": IF F$="No Data" THEN PRINT '''" NO FILE EXISTS TO SAVE ": RETURN 
 3182 INPUT "Select by # ";I$: ON ERR GO TO 3180: LET a=INT VAL ("0"+I$): ON ERR RESET : IF a<1 OR a>3 THEN GO TO 3180
 3183 IF a=3 THEN RETURN 
 3184 IF a=1 THEN LET I$=F$: GO TO 3187
 3185 INPUT "File Identifier? ";I$: LET I$=I$+".AZ": PRINT AT xx,12;I$: IF LEN I$<4 OR LEN I$>9 THEN PRINT "INVALID FILE NAME, TRY AGAIN": PAUSE 120: GO TO 3180
 3186 LET F$=I$
 3187 PRINT AT 20,3;" SAVING ";I$;"",: SAVE I$ DATA z(): PRINT AT 20,3;I$;" SAVED",,: RETURN 
 3201 DATA "a",iv,"X0=","; Y="," to ","; Width="
 3202 DATA "b",iv,"Y0=","; X="," to ","; Width="
 3203 DATA "c",iv,"Y0=",",X0=","; H=",", W="
 3204 DATA "d",iv,"Y0=",", X0=",", Rx=",", Ry/Rx="
 3205 DATA ("f" AND z(l,v)<z)+("e" AND z(l,v)>z),iv,"X1=",", Y1=","; X2=","; Width="
 3206 DATA ("h" AND z(l,v)<z)+("g" AND z(l,v)>z),iv,"X1=",", Y1=","; X2=","; Width="
 3207 DATA "i",v,"Y1=",", X1=","; Y2=",", X2=","; Width="
 3208 DATA "j",iii,"Y0=",", X0=","; Rad="
 3209 DATA "k",iii,"Y0=",", X0=","; Rad="
 3210 DATA CHR$ (155+z(l,six)),v,"X0=",", Y0=","; Rx=","; Ry/Rx=","; Quad="
 3230 CLS : PRINT "     WIDJUP EDIT SERVICE",""'''" 1  a  Line"," 7  g  Jog"''" 2  b  Line"," 8  h  Jog"''" 3  c  Box"," 9  i  Slant"''" 4  d  Circle","10  j  Pad"''" 5  e  45 Deg","11  k  Pad"''" 6  f  45 Deg","12  n   Quadrant"'''" Items oriented as they appear  DISPLAYED, not as printed."
 3231 INK 2: FOR n=0 TO 5: PLOT 30,62+16*n: DRAW 0,11: DRAW 11,0: DRAW 0,-11: DRAW -11,0: NEXT n: FOR n=0 TO 5: PLOT 158,62+16*n: DRAW 0,11: DRAW 11,0: DRAW 0,-11: DRAW -11,0: NEXT n: INK 0: RETURN 
 3301 DATA "a","   1  At X=","   2     Y=","   3  To Y=","   4 Width=","      -----"
 3302 DATA "b","   1  At Y=","   2     X=","   3  To X=","   4 Width=","     -----"
 3303 DATA "c","   1  At Y=","   2     X=","   3 HighY=","   4 WideX=","     -----"
 3304 DATA "d","   1  At Y=","   2     X=","   3    Rx=","   4 Ry/Rx=","     -----"
 3305 DATA "e","   1 From X=","   2      Y=","   3   To X=","   4  Width=","     -----"
 3306 DATA "f","   1 From X=","   2      Y=","   3   To X=","   4  Width=","     -----"
 3307 DATA "g","   1 From X=","   2      Y=","   3   To X=","   4  Width=","     -----"
 3308 DATA "h","   1 From X=","   2      Y=","   3   To X=","   4  Width=","     -----"
 3309 DATA "i","   1 From Y=","   2 From X=","   3   To Y=","   4   To X=","   5  Width="
 3310 DATA "j","   1  At Y=","   2     X=","   3 Radius=","     -----","     -----"
 3311 DATA "k","   1  At Y=","   2     X=","   3 Radius=","     -----","     -----"
 3312 DATA CHR$ (155+z(c,6)),"   1  At Y=","   2     X=","   3    Rx=","   4 Ry/Rx=","   5  Quad="
 4010 CLS : LET L=40: LET yo=12: LET xo=36: PLOT xo-i,yo+161: DRAW z,-162: DRAW 214,z: DRAW z,162: DRAW -214,z: PRINT AT z,iii;"4";AT 5,iii;"3";AT 10,iii;"2";AT 15,iii;"1";AT XX,iii;"0";AT 21,4;"0    1    2 >X 3    4    5";AT 12,ii;"Y"'"  ^";
 4011 FOR n=12 TO 173 STEP 4: PLOT 33,n: DRAW ii,z: PLOT 249,n: DRAW ii,z: NEXT n: FOR n=36 TO 248 STEP 4: PLOT n,9: DRAW z,ii: PLOT n,173: DRAW z,ii: NEXT n: RETURN 
 4060 IF z(i,i)<i THEN LET F$="No Data"
 4061 BORDER 7: CLS : PRINT '"      WIDJUP EDIT SERVICE"," ";F$,,""
 4062 PRINT AT xx,i;"ESCFIXSELADD < PUTCUT > MAPDEL";AT 21,i;" 1  2  3  4  5  6  7  8  9  0 "
 4063 FOR N=7 TO 230 STEP 24: PLOT n,z: DRAW z,16: DRAW 24,z: DRAW z,-16: DRAW -24,z: NEXT N
 4064 REM spare
 4065 LET left=here-ii: IF left<i THEN LET left=i
 4066 PRINT AT 7,z,,,,,,,,,,,,,,,,,,,,,,: GO SUB He
 4070 ON ERR RESET : LET a=CODE INKEY$
 4071 IF a=4 THEN GO TO 4096
 4072 IF a=5 THEN GO TO 5000
 4073 IF a=6 THEN GO TO 5010
 4074 IF a=7 THEN RETURN 
 4075 IF a=8 THEN LET here=here-(i AND here>i): GO TO WE
 4076 IF a=9 THEN LET here=here+(i AND here<z(i,i)): GO TO WE
 4077 IF a=10 THEN PRINT AT 10,12;" PASTING ";: GO SUB 4099: FOR n=i TO 11: LET z(here+i,n)=a(n): NEXT n: GO TO WE
 4078 IF a=11 THEN PRINT AT 10,12;" CUTTING ";: DIM a(11): FOR n=i TO 11: LET a(n)=z(here+i,n): NEXT n: GO SUB 4101: GO TO WE
 4079 IF a=12 THEN PRINT AT 10,11;" DELETING ";: GO SUB 4101: GO TO WE
 4080 IF a=13 OR a=14 THEN GO TO Hk
 4081 IF a=15 THEN GO SUB 4010: LET c=here+i: FOR n=i TO LEN f$: PRINT PAPER 5;AT n,i;f$(n): NEXT n: PRINT AT 18,z;"#";here;: FOR n=c TO c: GO SUB z(c,i)+3082: GO SUB 3076: NEXT n: GO SUB Key: GO TO SE
 4082 GO TO Hk
 4096 ON ERR GO TO HK: INPUT "SELECT ITEM by # ";I$: LET here=VAL ("0"+I$): ON ERR RESET : IF here<i THEN LET here=i
 4097 IF here>z(i,i) THEN LET here=z(i,i)
 4098 GO TO WE
 4099 IF z(i,i)=z THEN LET z(i,i)=i: LET here=i: RETURN 
 4100 GO TO 300
 4101 IF here=z THEN GO SUB Err: RETURN 
 4102 GO TO 302
 4500 PRINT "      WIDJUP EDIT SERVICE          DATA ENTRY AND MODIFICATION  "'',"ITEM # ";here;" ";: READ I$: PRINT " ";I$;" "': PRINT "  0  CANCEL ": FOR k=ii TO six: READ I$: PRINT I$,z(c,k): NEXT k: FOR k=7 TO 11: PRINT "   ";k-i,z(c,k): NEXT k
 4501 PRINT AT 10,v;"Y Copies..";AT 11,v;"Y Pitch=";AT 12,v;"X Copies..";AT 13,v;"X Pitch=";AT 14,ii;"10   Eraser.."'" 11  INSTALL "
 4502 PLOT 0,175: DRAW 255,z: DRAW z,-150: DRAW -255,z: DRAW z,150
 4503 IF cc=12 THEN PRINT AT 20,0;"QUADRANT SPRITES"'"1=m,2=n,3=o,4=p,5=q,6=r,7=s,8=t";
 4510 RETURN 
 4901 DATA i,i,i,.02,z,i,z,i,z,z
 4902 DATA i,i,i,.02,z,i,z,i,z,z
 4903 DATA i,i,.8,.3,z,i,z,i,z,z
 4904 DATA i,i,.03,i,z,i,z,i,z,z
 4905 DATA i,i,1.5,.02,z,i,z,i,z,z
 4906 DATA i,i,1.5,-.02,z,i,z,i,z,z
 4907 DATA i,i,1.5,.02,z,i,z,i,z,z
 4908 DATA i,i,1.5,-.02,z,i,z,i,z,z
 4909 DATA ii,i,i,ii,.02,i,z,i,z,z
 4910 DATA i,i,.04,z,z,2,.3,7,.1,z
 4911 DATA i,i,.04,z,z,7,.1,2,.3,z
 4912 DATA i,i,.04,i,5,i,z,i,z,z
 5000 GO SUB ST: LET z(i,i)=z(i,i)+i: LET here=z(i,i)
 5001 ON ERR RESET : INPUT "Select by # ";I$
 5002 ON ERR GO TO Add+i: LET a=VAL ("0"+I$): ON ERR RESET : IF a<i OR a>12 THEN GO SUB Err: GO TO Add+i
 5003 LET c=here+i: LET fixx=z: RESTORE 4900+a: FOR n=2 TO 11: READ a1: LET z(c,n)=a1: NEXT n
 5004 LET g$="010203040505060607080910": LET cc=a+a-1: LET z(c,i)=VAL (g$(cc TO cc+1)): IF a=6 OR a=8 THEN LET z(c,5)=-z(c,5)
 5005 LET cc=a: GO TO Fix+1
 5010 LET c=here+i: LET fixx=i: DIM e(11): FOR n=i TO 11: LET e(n)=z(c,n): NEXT n: LET cc=e(i): LET cc=cc+(i AND cc>5)+(i AND cc>6)+(i AND (cc=5 OR cc=6) AND e(5)<z): IF here<1 THEN GO SUB Err: GO TO WE
 5011 CLS : RESTORE 3300+cc: GO SUB 4500
 5012 ON ERR RESET : INPUT "Select ";I$: IF I$="" THEN GO SUB Err: GO TO Fix+ii
 5013 LET a1=I$( TO i)="0": IF (a1 AND Fixx=i) THEN FOR n=i TO 11: LET z(here+i,n)=e(n): NEXT n: GO TO SE
 5014 IF (a1 AND Fixx=z) THEN LET z(here+i,i)=z: LET z(i,i)=z(i,i)-i: LET here=z(i,i): GO TO SE
 5015 ON ERR GO TO Fix+ii: LET a=VAL I$: ON ERR RESET : IF a<1 OR a>11 THEN GO SUB Err: GO TO Fix+ii
 5016 IF a=11 THEN GO TO 5022
 5017 ON ERR RESET : LET Row=a+4: PRINT AT Row,16; OVER i;"     ";AT Row,16;: INPUT "Value=";I$
 5018 ON ERR GO TO 5021: LET bb=VAL ("0"+I$): ON ERR RESET : IF a=4 THEN IF cc=6 OR cc=8 THEN LET bb=-ABS bb
 5019 IF cc=12 AND a=5 THEN IF bb<1 OR bb>8 THEN GO SUB Err: GO TO Fix+ii
 5020 LET z(c,a+i)=bb: PRINT bb;"    ";: GO TO 5012
 5021 ON ERR RESET : GO SUB Err: GO TO 5017
 5022 IF f$<>"No Data" THEN GO TO SE
 5023 ON ERR RESET : INPUT "FILE NAME (less.AZ ext)? ";f$
 5024 IF f$="" OR LEN f$>six THEN GO SUB Err: GO TO 5023
 5025 LET f$=f$+".AZ": GO TO SE
 6000 FOR n=1 TO 20: FOR l=1 TO 10: PRINT AT n-1,l+l+l-3;CODE j$(n,l): NEXT l: NEXT n: STOP : GO TO 6000
 7770 GO SUB 7772: GO SUB 7771: FOR j=1 TO 242: POKE LD0+j-1,CODE U$(j): NEXT j: RANDOMIZE USR (LD0+49): LET Wa=PEEK 23631+256*PEEK 23632: LET Wc=INT (LD0/256): POKE Wa+15,LD0-256*Wc: POKE Wa+16,Wc: RETURN 
 7771 LET LD0=26995: RETURN 
 7772 RESTORE 7773: DIM O$(13): FOR n=1 TO 13: READ i$: LET X=VAL I$: LET O$(n)=CHR$ X: NEXT n: RETURN 
 7773 DATA "161","162","164","165","175","188","235","229","232","233","234","45","49"
 8000 CLS : IF f$="No Data" THEN INPUT "Filename? ";f$: CLS 
 8002 PRINT AT 17,0;"      FILE UPDATE SERVICE"," 1 select file"," 4 edit"," 2 store  file"," 5 undo"," 3 copy   file"," 6 quit",""
 8004 INPUT "SELECT FUNCTION BY # ";I$: IF NOT LEN I$ THEN GO SUB Err: GO TO 8004
 8006 LET a=VAL I$: IF a<i OR a>6 THEN GO TO 8004
 8008 GO TO 8000+10*a
 8010 INPUT "Frame=";s: LET H$=F$( TO 3)+STR$ s: LOAD H$ CODE : GO TO 8002
 8020 SAVE H$ CODE 16384,4096: GO TO 8002
 8030 INPUT "Are you SURE? (Yes)";q$: IF q$<>"Y" THEN GO TO 8002
 8032 SAVE H$ CODE 16384,4096: GO TO 8002
 8040 INPUT "COLUMN? ";c: LET row=INT (c/32): LET col=c-32*row: PRINT AT row,col; OVER i;" ";
 8042 INPUT "WHAT? ";W$
 8050 FOR n=0 TO 8 STEP 4: PRINT AT row+n,col; OVER i;W$;: NEXT n: GO TO 8004
 8060 STOP : GO TO 8000
 8100 CLS : PRINT " IMAGE FILE COPY SERVICE";AT 2,1;"Each frame loads from tape and";AT 3,1;"is saved again.": PAUSE 0
 8102 REM  was Oliger-only
 8104 INPUT "Filename? ";F$;" From: ";from;" To: ";to
 8106 CLS : FOR n=from TO TO : LET h$=f$( TO 3)+STR$ n: LOAD h$CODE 
 8108 SAVE h$ CODE 16384,4096
 8110 NEXT n
 8140 STOP : GO TO 8100
 8995 ON ERR RESET : CLS : PRINT AT 10,9;" WORKING ";: LET s=1: LET u=s: LET kk=s: LET a=s: LET b=s: LET c=s: LET d=s: LET f=s: LET a1=s: LET b1=s: LET j=s: FOR L=s TO s: NEXT L: LET ff=s: LET ee=44: LET aa=201: LET i=s: LET w=s
 8996 LET k1=120/216: LET z=s-s: FOR n=s TO s: NEXT n: FOR k=s TO s: NEXT k: LET e=s: LET g=s: LET h=s: LET lk=100
 8997 LET ii=i+i: LET iii=ii+i: LET iv=ii+ii: LET v=iv+i: LET six=v+s: LET xx=iv*v: LET drive=z: LET Gdrive=i: LET Ddrive=drive: LET Here=s
 8998 LET Main=9000: LET Me=9006: LET Err=Me+i: LET Key=Err+i: LET Dump=451: LET SR=3000: LET SE=4060: LET WE=4065: LET ST=3230: LET SD=6000: LET WD=6000: LET HE=305: LET HK=4070: LET ADD=5000: LET FIX=5010: LET jj=449: LET rr=1302
 8999 DIM z(100,11): LET F$="No Data": LOAD "CAD_CU"CODE : LOAD "J$T" DATA j$(): DIM u$(242): FOR j=1 TO 242: LET u$(j)=CHR$ PEEK (26994+j): NEXT j: GO SUB 7770
 9000 ON ERR RESET : INVERSE z: PAPER 7: INK z: BORDER 6: CLS : PRINT " The WIDJUP Co. (C)1991..CAD#5             MAIN MENU"," FUNCTION","DESCRIPTION","": PRINT '" 1  LOAD","PCB Data Array"''" 2  CREATE","New PCB"''" 3  EDIT","PCB Data Array"''" 4  DISPLAY","PCB"''" 5  DIRECTORY","Drives 0-4"''" 6  REPORT","LPRINT Data"''" 7  GENERATE","PCB Image"''" 8  COPY","From Image File"''" 9  SAVE","PCB Data Array"
 9001 INPUT "SELECT by # ";I$: IF I$="" THEN GO TO Me
 9002 IF I$="q" OR I$="Q" THEN STOP 
 9003 ON ERR GO TO Me: LET n=VAL I$: ON ERR RESET : IF n>9 OR n<i THEN GO TO Me
 9004 GO SUB SR+xx*n
 9005 GO SUB Key: GO TO Main
 9006 ON ERR RESET : GO SUB Err: GO TO Main+i
 9007 PRINT #i;AT z,z;" BAD INPUT.  TRY AGAIN. ": PAUSE 60: PRINT #i;AT z,z,,: RETURN 
 9008 PRINT #i;AT z,six;" PRESS ANY KEY ";: PAUSE z: RETURN 
 9093 PRINT AT xx-ii,i;" DISK FULL. INSTALL ANOTHER. "'"   Enter ""GO"" when ready.": FOR n=1 TO 8: BEEP .3,10: BEEP .3,22: NEXT n
 9094 INPUT "Enter ""GO"" when ready.";W$: IF LEN W$<2 THEN GO TO 9096
 9095 IF W$( TO 2)="GO" THEN RETURN 
 9096 GO SUB Err: GO TO 9094
 9500 FOR n=i TO xx: GO SUB 9501: PAUSE z: NEXT n: STOP : GO TO 9500
 9501 RESTORE 9502: CLS : PRINT "GROUP ";n,'': FOR k=i TO 11: READ i$: PRINT i$;CODE j$(n,k);"  ",CODE o$(k): NEXT k: RETURN 
 9502 DATA " 1  col "," 2 ro*8 "," 3 dblh "," 4 lins "," 5 marg "," 6 wide "," 7  n/l "," 8 step "," 9 Gmod ","10 Nlsb ","11 Nmsb "
 9990 POKE 26876,167
 9991 INPUT "Date? ";i$: LPRINT "lN";CHR$ 6;: LPRINT #5'"CAD_BE Listing Oliger/Epson";i$'': LLIST #5: LPRINT "lO";CHR$ 12;: STOP 
 9999 CLEAR : SAVE "CAD_BE" LINE 8995: GO TO 8995

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.