home *** CD-ROM | disk | FTP | other *** search
/ DTP Toolbox / DTPToolbox.iso / propage4.0 / arexx / barcodes.pdrx < prev    next >
Encoding:
Text File  |  1995-09-08  |  23.1 KB  |  714 lines

  1. /*
  2. Routine to generate bar codes for Pro Draw. Consumer codes (UPC, EAN and ISBN can be drawn singly; others can also be drawn in multiple copies for sheets of labels. 
  3. Written by Don Cox, Jan-Dec. '94. Copyright. Not Public Domain.
  4. Requires the files BarCodesEAN.rexx and NumberData.rexx (both in Rexx:). 
  5. */
  6. /* $VER: BarCodes Sept 95 */
  7.  
  8. /*call open("STDERR","ram:trace","W")
  9. trace r*/
  10.  
  11. oldunits = pdm_GetUnits()
  12. call pdm_SetUnits(2) /* work in metric throughout */
  13. call pdm_AutoUpdate(0)
  14.  
  15. if ~show(l, "gdarexxsupport.library") then
  16.    if ~addlib("gdarexxsupport.library",0,-30) then
  17.       exit_msg("Please install the gdarexxsupport.library in your libs: directory before running this Genie.")
  18.  
  19. numeric digits 14
  20. cr = '0a'x
  21.  
  22. chosen = getclip(pduschosen)
  23. if chosen = "" then chosen = "NULL"
  24.  
  25. codelist = "ISBN" ||cr|| "ISBNplus5"||cr||"EAN13"||cr|| "EAN13plus2"||cr|| "EAN13plus5" ||cr|| "EAN8" ||cr|| "EAN8plus2" ||cr|| "EAN8plus5" ||cr|| "UPC-A" ||cr|| "UPC-Aplus2" ||cr|| "UPC-Aplus5"||cr|| "UPC-E" ||cr|| "UPC-Eplus2" ||cr|| "UPC-Eplus5" ||cr|| "ITF (single)"||cr|| "ITF (multiple)"||cr||"Codabar (single)"||cr||"Codabar (multiple)" ||cr|| "Code39 (single)" ||cr|| "Code39 (multiple)"
  26. /* Putting an underscore in front of the default item preselects it */
  27. chosenpos = pos(chosen,codelist)
  28. if chosenpos~=0 then codelist = insert("_",codelist,chosenpos-1)
  29.  
  30. chosen = pdm_SelectFromList("Select Barcode Format",20,20,2,codelist)
  31. if chosen = "" then exit_msg("Aborted by user")
  32. call setclip(pduschosen,chosen)
  33.  
  34.  
  35. box = pdm_ClickArea("Drag out box to contain code")
  36. if box = "" then exit_msg("No box")
  37.  
  38. numberprompt = getclip(pdusnumbers)
  39.  
  40. colour1 = getclip(pduscolour1) /* colour selector is in EAN section only */
  41. colour2 = getclip(pduscolour2)
  42. if colour1 = '' then colour1 = "WHITE"
  43. if colour2 = '' then colour2 = "BLACK"
  44. call setclip(pduscolour1,colour1)
  45. call setclip(pduscolour2,colour2)
  46.  
  47. select
  48.     when left(chosen,4) = "ISBN" then call EAN
  49.     when left(chosen,3) = "EAN" then call EAN
  50.     when left(chosen,3) = "UPC" then call EAN
  51.     otherwise call multi()
  52.     end
  53.  
  54. call numberdata.rexx(,close) /* Clear clips for drawing numerals */
  55. exit_msg("Finished")
  56. end
  57.  
  58. /* +++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++ */
  59.  
  60. /* Do single or multiple labels */
  61. multi:
  62.  
  63. multiple = 0
  64. if pos("multi",chosen)~=0 then multiple = 1
  65. first = 1 /* do some things first time only */
  66.  
  67. inkspread = getclip(pdusspread)
  68. if inkspread = '' then inkspread = 0.00
  69. numberfont = getclip(pdusnumberfont)
  70. if numberfont = "" then numberfont = "B"
  71.  
  72. parse var box cornerX cornerY cornerX2 cornerY2
  73. cornerY2 = strip(cornerY2) /* remove a space */
  74. boxwidth = abs(cornerX2-cornerX)
  75. boxheight = abs(cornerY2-cornerY)
  76. cpage = pdm_CurrentPage()
  77.  
  78. rows = 1 /* default */
  79. columns = 1
  80. numpages = 1
  81.  
  82. if multiple = 1 then do
  83.     numcodes = getclip(pdusnumcodes)
  84.     if numcodes = "" then numcodes=1
  85.     copies = getclip(pduscopies)
  86.     if copies = "" then copies = 1
  87.     pagewidth = getclip(pduspagewidth)
  88.     if pagewidth = "" then pagewidth = 210
  89.     pageheight = getclip(pduspageheight)
  90.     if pageheight = "" then pageheight = 297
  91.     marginX = getclip(pdusmarginX)
  92.     if marginX = "" then marginX = 12
  93.     marginY = getclip(pdusmarginY)
  94.     if marginY = "" then marginY = 12
  95.     rows = getclip(pdusrows)
  96.     if rows = "" then rows = 5
  97.     columns = getclip(pduscolumns)
  98.     if columns = "" then columns = 3
  99.  
  100.     mstring = "# of codes:"numcodes ||cr|| "Copies of each:"copies ||cr|| "Page Width (mm):"pagewidth ||cr|| "Page Height (mm):"pageheight ||cr|| "Left Margin (mm):"marginX ||cr|| "Top Margin (mm):"marginY ||cr|| "Rows:"rows ||cr|| "Columns:"columns
  101.     form = pdm_GetForm("Enter numbers",28,mstring)
  102.     parse var form numcodes "0a"x copies "0a"x pagewidth "0a"x pageheight "0a"x marginX "0a"x marginY "0a"x rows "0a"x columns
  103.  
  104.     numcodes = strip(numcodes,,' -')
  105.     copies = strip(copies,,' -')
  106.     pagewidth = strip(pagewidth,,' -')
  107.     pageheight = strip(pageheight,,' -')
  108.     marginX = strip(marginX,,' -')
  109.     marginY = strip(marginY,,' -')
  110.     rows = strip(rows,,' -')
  111.     columns = strip(columns,,' -')
  112.  
  113. /* Set clips before checking, so they can be edited */
  114.     call setclip(pdusnumcodes,numcodes)
  115.     call setclip(pduscopies,copies)
  116.     call setclip(pduspagewidth,pagewidth)
  117.     call setclip(pduspageheight, pageheight)
  118.     call setclip(pdusmarginX, marginX)
  119.     call setclip(pdusmarginY, marginY)
  120.     call setclip(pdusrows,rows)
  121.     call setclip(pduscolumns, columns)
  122.  
  123.     if ~datatype(numcodes,n) then exit_msg("Number of codes not valid")
  124.     if ~datatype(copies,n) then exit_msg("Number of copies not valid")
  125.     if ~datatype(pagewidth,n) then exit_msg("Page width not valid")
  126.     if ~datatype(pageheight,n) then exit_msg("Page height not valid")
  127.     if ~datatype(marginX,n) then exit_msg("Margin setting not valid")
  128.     if ~datatype(marginY,n) then exit_msg("Margin setting not valid")
  129.     if ~datatype(rows,n) then exit_msg("Number of rows not valid")
  130.     if ~datatype(columns,n) then exit_msg("Number of columns not valid")
  131.  
  132.     numcodes = trunc(numcodes)
  133.     copies = trunc(copies)
  134.     rows = trunc(rows)
  135.     columns = trunc(columns)
  136.  
  137.     pagewidth = pagewidth/10 /* convert to cm */
  138.     pageheight = pageheight/10
  139.     marginX = marginX/10
  140.     marginX2 = 2*marginX
  141.     marginY = marginY/10
  142.     marginY2 = 2*marginY
  143.     numlabels = numcodes*copies
  144.     LabelsPerPage = rows*columns
  145.     numpages = (numlabels%LabelsPerPage)+1
  146.     labelwidth = (pagewidth-marginX2)/columns
  147.     labelheight = (pageheight-marginY2)/rows
  148.     boxwidth = min(boxwidth,labelwidth*0.9)
  149.     boxheight = min(boxheight,labelheight*0.9)
  150.     call pdm_SetPageSize(cpage, pagewidth, pageheight)
  151.  
  152.     /* if page is not clear, make a new one */
  153.     firstobject = pdm_PageFirstObj() 
  154.     if firstobject~=0 then cpage = addpages(1,cpage)
  155.  
  156.     end
  157.  
  158. checkprompt = getclip(pduscheckprompt)
  159. if checkprompt = "" then checkprompt = "Y"
  160. fontprompt = getclip(pdusfontprompt)
  161. if fontprompt = "" then fontprompt = "N"
  162.  
  163.  
  164. label = 1
  165.  
  166. do p = 1 to numpages
  167.     if p>1 then cpage = addpages(1,cpage)
  168.  
  169.     do r = 1 to rows
  170.         if rows>1 then do
  171.             cornerY = (labelheight*(r-1))+marginY
  172.             cornerY2 = cornerY+boxheight
  173.             end
  174.         do c = 1 to columns
  175.             if columns>1 then do
  176.                 cornerX = (labelwidth*(c-1))+marginX
  177.                 cornerX2 = cornerX + boxwidth
  178.                 end
  179.             success = BarCodeMain(chosen, box, colour1, colour2) /* call main program */
  180.             label = label+1
  181.             if label>numlabels then leave p
  182.             end /* of columns */
  183.         end /* of rows */
  184.  
  185.     end /* of pages */
  186.  
  187. return
  188.  
  189. /* ++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++ */
  190.  
  191. /* Routine to draw single bar codes, using Pro Draw. */
  192.  
  193. BarCodeMain:
  194.  
  195. trace n
  196. parse arg chosen, box, colour1, colour2
  197. numeric digits 14
  198. barcodedone = 0
  199. cr = '0a'x
  200.  
  201. identity = 1 /* count objects */
  202. curves. = ""
  203.  
  204. select
  205.     when left(chosen,3) = "ITF" then call ITF
  206.     when left(chosen,7) = "Codabar" then call Codabar
  207.     when left(chosen,6) = "Code39" then call Code39
  208.     otherwise exit_msg("Aborted by User")
  209.     end
  210.  
  211.  
  212.  
  213. identity = identity-1
  214. call pdm_SelectObj(curves.1,curves.identity)
  215. call pdm_GroupObj()
  216.  
  217. trace n
  218. barcodedone = 1
  219. return barcodedone
  220. end
  221.  
  222. /* +++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ */
  223.  
  224. EAN:
  225. success = BarCodesEAN.rexx(chosen, box, colour1, colour2, numberprompt, oldunits) /* call separate EAN program */
  226. if success~=1 then exit_msg(success)
  227. return
  228.  
  229. /* +++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ */
  230.  
  231. /* Final way out */
  232. exit_msg: procedure expose oldunits
  233. do
  234.     parse arg message
  235.  
  236.     if message ~= '' then call pdm_Inform(1,message,)
  237.     call pdm_ClearStatus()
  238.     call pdm_SetUnits(oldunits)
  239.     call pdm_UpdateScreen(0)
  240.     call pdm_AutoUpdate(1)
  241.     exit
  242. end
  243.  
  244. /* ++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ */
  245.  
  246. /* Create a new page without adding a blank page at end of document */
  247.  
  248. addpages: procedure
  249.     parse arg n, cpage
  250.         newpage = pdm_CreatePage(cpage,n,)
  251.         newpage = pdm_MovePage(newpage+n,newpage)
  252.         cpage = pdm_GoToPage(newpage+n)
  253.     return cpage
  254.  
  255.  
  256. /* ++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++++++ */
  257.  
  258. drawbar:
  259.  
  260. trace n
  261. currentfill = colour2
  262. barleft2 = barleft+inkspread
  263. barright2 = barright-inkspread
  264. obj = pdm_DrawRectangle(barleft2, bartop, barright2, barbottom)
  265. call pdm_SetLineWeight(obj, 0.00)
  266. call pdm_SetFillPattern(obj,1, currentfill)
  267. curves.identity = obj
  268. identity = identity+1
  269.  
  270. return
  271.  
  272. /* +++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++++ */
  273.  
  274. /* Draw string of numbers */
  275. numberdraw:
  276.  
  277. trace n
  278. call pdm_ShowStatus("  Drawing Numerals..")
  279. numlength = length(numbers)
  280. numberleft = cornerX+(boxwidth/2)- ((charwidth+(unitwidth*2))* (numlength/2))
  281.  
  282. if upper(nfset) ~= "N" then do
  283.     fsnumber = 3
  284.     fontselectstring = '"Abort","Select Font","Use Internal Font"'
  285.     if pos("39",chosen)~=0 then do
  286.         fontselectstring = '"Abort","Select Font"'
  287.         fsnumber = 2
  288.         end
  289.     fss ='fontselect = pdm_Inform('||fsnumber||',"Select font...",'||fontselectstring||')'
  290.     interpret fss
  291.     if fontselect = 0 then exit_msg("User aborted program")
  292.     if fontselect = 1 then do
  293.         fontsavail = strip(pdm_GetFontList(),"T","0a"x)
  294.         numberfont = pdm_SelectFromList("Select Font",23,18,0, fontsavail)
  295.         call setclip(pdusnumberfont, numberfont)
  296.         nfset = "N" /* Don't select again if multiple bars */
  297.         end
  298.     if fontselect ~=1 then numberfont = "B"
  299.     end
  300.  
  301. if numberfont = "B" then do
  302.     if first = 1 then call numberdata.rexx() /* set data for numbers as clips */
  303.     scaleX = charwidth/4.5 /* this arbitrary number depends on the size of  characters in the data strings */
  304.     scaleY = scaleX   /* keep proportions - ignore box height */
  305.     do i = 1 to numlength
  306.         thisnumber = substr(numbers, i,1)
  307.         call drawnumber /* draw single digit */
  308.         numberleft = numberleft + charwidth +(unitwidth*2)/* move to next position*/
  309.         end
  310.     end
  311.  
  312. else do
  313.     numbergap = cornerY2-barbottom
  314.     points = numbergap *0.8 *28.3 /* 28.3 is cm to points */ 
  315.     call pdm_InitText(numberfont,points)
  316.     numberbottom = cornerY2 - (numbergap*0.2)
  317.     nresult = pdm_Text(numbers, numberleft, numberbottom)
  318.     Xend = word(nresult,1) /* Text returns coords for next char */
  319.     numlength2 = Xend-numberleft /* Recalculate position */
  320.     numberleft2 = cornerX+((boxwidth/2)- (numlength2/2))
  321.     lastchar = pdm_DocLastObj()
  322.     firstchar = pdm_GroupFirstObj(lastchar)
  323.     shift = numberleft2-numberleft
  324.     call pdm_MoveObj(firstchar, shift, 0)
  325.     do n=firstchar to lastchar
  326.         curves.identity = n
  327.         identity = identity+1
  328.         end
  329.     end
  330.  
  331. return
  332.  
  333.  
  334.  
  335. /* ++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++++++++ */
  336.  
  337. /* Draw single number using data in clips set by numberdata.rexx */
  338. drawnumber:
  339.  
  340. thisclip = "pdusnumdata"||thisnumber
  341. thisdata = getclip(thisclip) 
  342. parse var thisdata boxsizeX "0a"x boxsizeY "0a"x numstring1 "0a"x numstring2 "0a"x numstring3
  343.  
  344.     call pdm_initplot(numberleft, numbertop, scaleX, scaleY, 0)
  345.     call pdm_PlotBezier(numstring1)
  346.     obj = pdm_ClosePlot()
  347.     curves.identity = obj
  348.     call pdm_SetLineWeight(obj, 0.00)
  349.     call pdm_SetFillPattern(obj,1, colour2)
  350.     identity = identity+1
  351.     
  352.     if numstring2 ~="" then do /* holes in numerals - use solid fills, not compound objects */
  353.         call pdm_initplot(numberleft, numbertop, scaleX, scaleY, 0)
  354.         call pdm_PlotBezier(numstring2)
  355.         obj = pdm_ClosePlot()
  356.         curves.identity = obj
  357.         call pdm_SetLineWeight(obj, 0.00)
  358.         call pdm_SetFillPattern(obj,1, colour1)
  359.         identity = identity+1
  360.         end
  361.     if numstring3 ~="" then do /* some have 2 holes */
  362.         call pdm_initplot(numberleft, numbertop, scaleX, scaleY, 0)
  363.         call pdm_PlotBezier(numstring3)
  364.         obj = pdm_ClosePlot()
  365.         curves.identity = obj
  366.         call pdm_SetLineWeight(obj, 0.00)
  367.         call pdm_SetFillPattern(obj,1, colour1)
  368.         identity = identity+1
  369.         end
  370. return
  371.  
  372. /* +++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++ */
  373.  
  374. /* draw background rectangle */
  375. drawrectangle:
  376. currentfill = colour1
  377. boxright = cornerX + boxwidth
  378. boxbottom = cornerY + boxheight
  379. obj = pdm_DrawRectangle(cornerX, cornerY, boxright, boxbottom)
  380. call pdm_SetLineWeight(obj, 0.00)
  381. call pdm_SetFillPattern(obj,1, currentfill)
  382. curves.identity = obj
  383. identity = identity+1
  384. return
  385.  
  386. /* +++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++ */
  387.  
  388. checksum: procedure
  389. parse arg numstring
  390.  
  391. pos = length(numstring)
  392. total = 0
  393. do until pos<1
  394.     total = total+substr(numstring,pos,1)
  395.     pos=pos-2
  396.     end
  397. total = total*3
  398. pos= length(numstring)-1
  399. total2 = 0
  400. do until pos<1
  401.     total2 = total2+substr(numstring,pos,1)
  402.     pos=pos-2
  403.     end
  404. total=total+total2
  405. ch=10-(total//10)
  406. if ch=10 then ch = 0
  407.  
  408. numstring = numstring||ch
  409. return numstring
  410.  
  411. /* +++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++ */
  412.  
  413. /* Normalize numeric input */
  414. clearos: procedure
  415.  
  416. parse arg numbers
  417. position = 0 /* now replace O's with zeros */
  418. do forever
  419.     position = pos("O", numbers,position+1)
  420.     if position = 0 then break
  421.     numbers = delstr(numbers,position,1)
  422.     numbers = insert("0",numbers,position-1)
  423.     end
  424. position = 0 /* now replace o's with zeros */
  425. do forever
  426.     position = pos("o", numbers,position+1)
  427.     if position = 0 then break
  428.     numbers = delstr(numbers,position,1)
  429.     numbers = insert("0",numbers,position-1)
  430.     end
  431. position = 0 /* now remove hyphens */
  432. do forever
  433.     position = pos("-", numbers,position+1)
  434.     if position = 0 then break
  435.     numbers = delstr(numbers,position,1)
  436.     end
  437.  
  438. return numbers
  439.  
  440. /* +++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++ */
  441.  
  442.  
  443. ITF:
  444.  
  445. ITFcodes = "00110 10001 01001 11000 00101 10100 01100 00011 10010 01010"
  446.  
  447. if first = 1 then do
  448.     numberprompt = getclip(pdusnumbers)
  449.     prompt = "Code Numbers:"numberprompt ||cr|| "Ink Spread(mm):0.000" ||cr|| "Checksum? (Y/N):"checkprompt||cr|| "Set Font? (Y/N):"fontprompt
  450.     form = pdm_GetForm("Enter numbers",28,prompt)
  451.     parse var form numbers "0a"x inkspread "0a"x docheck "0a"x nfset
  452.     inkspread = inkspread/10   /* convert to cm */
  453.     dochecksum = 0
  454.     if upper(docheck)="Y" then dochecksum = 1
  455.     call setclip(pduscheckprompt, upper(docheck))
  456.     call setclip(pdusfontprompt, upper(nfset))
  457.  
  458.     if numbers = "" then exit_msg("User aborted genie")
  459.     numbers = space(numbers,0)  /* strip out all spaces */
  460.     call clearos(numbers)  /* replace any accidental letter Os with zeros */
  461.     ver =verify(numbers,"0123456789")
  462.     if ver~=0 then exit_msg("Letter "substr(numbers,ver,1)" among numbers")
  463.     call setclip(pdusnumbers, numbers)
  464.  
  465.     numlength = length(numbers)
  466.     if numlength//2~=0 then numbers = "0"||numbers /* must be even number of digits */
  467.     numlength = length(numbers)
  468.     shortlength = numlength
  469.     if dochecksum = 1 then numlength = numlength+2
  470.  
  471.     boxlength = (numlength*8)+8.5 /* 8.5 for start & stop codes */
  472.     unitwidth = (boxwidth/boxlength)*0.8
  473.     widebar = 2.5*unitwidth
  474.     charwidth = 6*unitwidth
  475.  
  476.     end
  477.  
  478. numbers = getclip(pdusnumbers)
  479. if first = 0 then numbers = numbers+((label-1)%copies)
  480. numbers = right(numbers,shortlength,0) /* restore leading zeros after maths */
  481. if dochecksum = 1 then numbers = "0"||checksum(numbers)
  482.  
  483. call drawrectangle
  484. call pdm_ShowStatus("  Drawing Bars..")
  485. currentfill = colour1
  486.  
  487. trace n
  488. /* Start code */
  489. bartop = cornerY +(0.1*boxheight)
  490. codebottom = cornerY+ (0.8*boxheight)
  491. barbottom = codebottom
  492. numbertop = cornerY+(boxheight*0.83)
  493.  
  494. barleft = cornerX+(boxwidth*0.1)
  495. do j = 1 to 4
  496.     barwidth = unitwidth
  497.     barright = barleft + barwidth
  498.     if currentfill = colour1 then call drawbar
  499.     else currentfill = colour1
  500.     barleft = barright
  501.     end
  502.  
  503. /* Number codes */
  504. do i = 1 to numlength by 2
  505.     pair1 = substr(numbers,i,1)
  506.     pair2 = substr(numbers,i+1,1)
  507.     barpattern1 = word(ITFcodes, pair1+1)
  508.     barpattern2 = word(ITFcodes, pair2+1)
  509.     do j = 1 to 5
  510.         barbit1 = substr(barpattern1,j,1)
  511.         barbit2 = substr(barpattern2,j,1)
  512.         barwidth1 = unitwidth
  513.         if barbit1 = 1 then barwidth1 = widebar
  514.         barwidth2 = unitwidth
  515.         if barbit2 = 1 then barwidth2 = widebar
  516.         barright = barleft + barwidth1
  517.         call drawbar
  518.         barleft = barright + barwidth2
  519.         end
  520.  
  521.     end
  522.  
  523. /* Stop code */
  524.     barwidth = widebar
  525.     barright = barleft + barwidth
  526.     call drawbar
  527.     barleft = barright+unitwidth
  528.     barright = barright+(2*unitwidth)
  529.     call drawbar
  530.  
  531. call numberdraw
  532. trace n
  533. first = 0 /* Don't do setup again */
  534.  
  535. return
  536.  
  537. /* ++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++++ */
  538.  
  539. Codabar:
  540.  
  541. if first = 1 then do
  542.  
  543.     codasearch = "0123456789-$:/.+ABCDTN*E"
  544. /* These codes are written as 0=narrow bar, 1=wide bar. Wide bars are 3 times width of narrow bars. */
  545. codacodes = "0000011 0000110 0001001 1100000 0010010 1000010 0100001 0100100 0110000 1001000 0001100 0011000 1000101 1010001 1010100 0010101 0011010 0101001 0001011 0001110 0011010 0101001 0001011 0001110"
  546. /* note codes for A & T, B & N, C & *, D & E are the same, and these pairs are used as start/stop codes. */
  547.  
  548.     numberprompt = getclip(pdusnumbers)
  549.     prompt = "Code Numbers:"numberprompt ||cr|| "Ink Spread(mm):0.000" ||cr|| "Start/Stop (A/B/C/D):A"||cr|| "Set Font? (Y/N):"fontprompt
  550.     form = pdm_GetForm("Enter numbers",28,prompt)
  551.     parse var form numbers "0a"x inkspread "0a"x startcode "0a"x nfset
  552.     inkspread = inkspread/10   /* convert to cm */
  553.     startcode = upper(startcode)
  554.     startcheck = verify(startcode,"ABCD")
  555.     call setclip(pdusfontprompt, upper(nfset))
  556.  
  557.  
  558.     if numbers = "" then exit_msg("User aborted genie")
  559.     numbers = space(numbers,0)  /* strip out all spaces */
  560.     numlength = length(numbers)
  561.     call setclip(pdusnumbers, numbers)
  562.  
  563.     call clearos(numbers)
  564.     ver =verify(numbers,codasearch)
  565.     if ver~=0 then exit_msg("Letter "substr(numbers,ver,1)" among numbers")
  566.  
  567.     call setclip(pdusnumbers, numbers)
  568.     end
  569.  
  570. numbers = getclip(pdusnumbers)
  571. if first = 0 then numbers = numbers+((label-1)%copies)
  572. numbers = right(numbers,numlength,0) /* restore leading zeros */
  573.  
  574. /* Start and stop codes */
  575. if startcheck = 0 then numbers2 = startcode||numbers||startcode
  576.  
  577. numlength2 = length(numbers2)
  578. boxlength = numlength2*11.5
  579. unitwidth = (boxwidth/boxlength) * 0.8
  580. widebar = 2.5*unitwidth
  581. charwidth = 10*unitwidth
  582. barleft = cornerX + (boxwidth*0.1)
  583. bartop = cornerY +(boxheight*0.1)
  584. barbottom = cornerY+(boxheight *0.8)
  585. numbertop = cornerY+(boxheight*0.85)
  586.  
  587. call drawrectangle
  588. call pdm_ShowStatus("  Drawing Bars..")
  589. currentfill = colour1
  590.  
  591. /* Number codes */
  592. do i = 1 to numlength2
  593.     thisnumber = substr(numbers2,i,1)
  594.     barpattern = word(codacodes, pos(thisnumber,codasearch))
  595.     do j = 1 to 7
  596.         barbit = substr(barpattern,j,1)
  597.         barwidth = unitwidth
  598.         if barbit = 1 then barwidth = widebar
  599.         barright = barleft + barwidth
  600.         if currentfill = colour1 then call drawbar
  601.         else currentfill = colour1
  602.         barleft = barright
  603.         end
  604.     barleft = barleft + unitwidth /* space between chars */
  605.     currentfill = colour1
  606.     end
  607. call numberdraw
  608. first = 0 /* Don't do setup again */
  609.  
  610. return
  611.  
  612. /* ++++++++++++++++++++++++++++++++++ ++++++++++++++++++++++++++++++++++ */
  613.  
  614. Code39:
  615.  
  616. if first = 1 then do
  617.     search39 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%*"
  618. /* Codes are listed here with 0s for narrow bars & 1s for wide bars. Wide bars should be 3 times the width of narrow, but are allowed to be as little as 2.2 times if the printer is accurate. Each pattern of bars is the same total width (3 wide bars & 6 narrow) and a space at least as wide as the narrow bars is left between the character patterns. This is the only common code which can be used like a typeface. */
  619. codes39 ="000110100 100100001 001100001 101100000 000110001 100110000 001110000 000100101 100100100 001100100 100001001 001001001 101001000 000011001 100011000 001011000 000001101 100001100 001001100 000011100 100000011 001000011 101000010 000010011 100010010 001010010 000000111 100000110 001000110 000010110 110000001 011000001 111000000 010010001 110010000 011010000 010000101 110000100 011000100 010101000 010100010 010001010 000101010 010010100"
  620.  
  621.  
  622.     prompt = "Code Numbers:"numberprompt ||cr|| "Ink Spread(mm):"inkspread ||cr|| "Checksum? (Y/N):"checkprompt ||cr|| "Set Font? (Y/N):"fontprompt
  623.     if numberfont ="B" then prompt = "Code Numbers:"numberprompt ||cr|| "Ink Spread(mm):"inkspread ||cr|| "Checksum? (Y/N):"checkprompt
  624.     form = pdm_GetForm("Enter letters & numbers",28,prompt)
  625.  
  626.     parse var form numbers "0a"x inkspread "0a"x docheck "0a"x nfset
  627.     if numberfont ="B" then nfset = "Y" /* If no name, must select - can't use built-in font for Code39 */
  628.     if ~datatype(inkspread,n) then exit_msg("Invalid entry for ink spread: "inkspread)
  629.     call setclip(pdusspread,inkspread)
  630.     inkspread = inkspread/10   /* convert to cm */
  631.  
  632.     if numbers = "" then exit_msg("User aborted genie")
  633.     numbers = upper(numbers)  /* Spaces are allowed */
  634.     numlength = length(numbers)
  635.     call setclip(pdusnumbers, numbers)
  636.     call setclip(pduscheckprompt, upper(docheck))
  637.     call setclip(pdusfontprompt, upper(nfset))
  638.  
  639.  
  640.     ver =verify(numbers,search39)
  641.     if ver~=0 then exit_msg("Invalid character "substr(numbers,ver,1)" among numbers")
  642.     call setclip(pdusnumbers, numbers)
  643.     shortlength = length(numbers)
  644.  
  645.     end /* of things to do on first label */
  646.  
  647. numbers = getclip(pdusnumbers)
  648. if first = 0 then do /* have to split off any letters in the code - can't increment letters */
  649.     revnumbers = reverse(numbers) /* work forward from last char */
  650.     alphapos = verify(revnumbers,"1234567890")
  651.     alpha = reverse(substr(revnumbers,alphapos))
  652.     numeric = reverse(left(revnumbers,alphapos-1))
  653.     numericlength = length(numeric)
  654.     if numericlength ~= 0 then do
  655.         numeric = numeric+((label-1)%copies)
  656.         numeric = right(numeric,numericlength,0) /*restore leading zeros */
  657.         end
  658.     numbers = alpha||numeric
  659.     end
  660.  
  661.  
  662. if upper(docheck) = "Y" then do
  663.     checktotal = 0
  664.     do i = 1 to numlength
  665.         thischar = substr(numbers,i,1)
  666.         checkvalue = pos(thischar,search39)-1
  667.         checktotal = checktotal+checkvalue
  668.         end
  669.     checkrem = checktotal//43
  670.     checkchar = substr(search39,checkrem+1,1)
  671.     numbers = numbers||checkchar
  672.     end
  673.  
  674.  
  675. /* Start and stop codes */
  676. numbers2 = "*"||numbers||"*"
  677.  
  678.  
  679. numlength2 = length(numbers2)
  680. boxlength = numlength2*14.5 /* 14.5 is width of 1 char + space */
  681. unitwidth = (boxwidth/boxlength) * 0.8
  682. widebar = 2.5*unitwidth
  683. charwidth = 13*unitwidth
  684. barleft = cornerX + (boxwidth*0.1)
  685. bartop = cornerY + (boxheight * 0.1)
  686. barbottom = cornerY+(boxheight *0.8)
  687. numbertop = cornerY+(boxheight *0.85)
  688.  
  689. call drawrectangle
  690. call pdm_ShowStatus("  Drawing Bars..")
  691. currentfill = colour1
  692.  
  693. /* Number codes */
  694. do i = 1 to numlength2
  695.     thisnumber = substr(numbers2,i,1)
  696.     barpattern = word(codes39, pos(thisnumber,search39))
  697.     do j = 1 to 9
  698.         barbit = substr(barpattern,j,1)
  699.         barwidth = unitwidth
  700.         if barbit = 1 then barwidth = widebar
  701.         barright = barleft + barwidth
  702.         if currentfill = colour1 then call drawbar
  703.         else currentfill = colour1
  704.         barleft = barright
  705.         end
  706.     barleft = barleft + unitwidth /* space between chars */
  707.     currentfill = colour1
  708.     end
  709. call numberdraw
  710. first = 0 /* Don't do setup again */
  711.  
  712. return
  713.  
  714.