For the SDT tool in PCB mode we allow users to create pads not only with the 
mouse, but also by entering the data in form of a string, which is some form of 
a batch mode. A PCB pad is basically a rectangle, with an attached number and a 
name. The text input string has this shape:

Pad x1, y1, +x2, +y2, Radius, dx, dy, N, Number, Name

First parameter "Pad" is an optional string with default value "Pad"

x1, y2 are floats in string form, same x2 and y2. But x2 and y2 can be prefixed 
with a "+" indicating that x2 and x2 is not the opposite corner of the pad but 
width and height. Radius is an optional float parameter with default value 
zero. dx, dy are optional float numbers with default zero, the describe the 
translation if we have to create not only one single pad, but multiple. N is an 
optional non negative integer which tells how many pads should be created. 
Finally Number and Name are plain optional strings.

Unfortunately it gets more complicated by the fact that the values do not have 
to be separated by comma , but semicolon or arbitrary whitespace should be also 
allowed. Example input:

Pad 100, 100 120.5;140.5 7.5 100 0 8 0 PAD

I tried using parseutils, but with that the proc fills the whole screen. 
strscan may work when the values are all just separated by one separator 
character, but with comma or semicolon and arbitrary whitespace it is difficult.

So use PEGS or RegEx? Or preprocess the string to something like

Pad,100,100,120.5,140.5,7.5,100,0,8,0,PAD

first, and then use strscan?

Of course we could use 10 different input fields in the GUI instead. Toy 
program may do it that way. But for a real application 10 input fields waste to 
much space and entering all that data into one entry field is faster and 
simpler -- generally user will separate data by space.

I have a similar simpler proc for entering size of the drawing area, and that 
one is already ugly:
    
    
    proc worldActivate(entry: Entry; pda: PDA) =
      var
        d: array[4, float] = [NaN, NaN, NaN, NaN]
        s: array[4, bool]
        t = entry.text
        i, j, k: int
        f: float
      i = 1
      entry.setIconFromIconName(EntryIconPosition.secondary, nil)
      for c in mitems(t):
        if c in {';', ','}:
          inc(i)
          c = ' '
        if c in {'0' .. '9'}:
          i = 0
        if i > 1:
          entry.setIconFromIconName(EntryIconPosition.secondary, "dialog-error")
          return
      while k < d.len:
        i = t.skipWhitespace(j)
        j += i
        if j == t.len:
          break
        s[k] = t[j] == '+'
        i = t.parseFloat(f, j)
        j += i
        if i > 0:
          d[k] = f
        inc(k)
      if k == 1:
        d[1] = d[0]
      elif k == 3:
        d[3] = d[2]
        s[3] = s[2]
      case k
      of 0:
        d = DefaultWorldRange
      of 1, 2:
        d[3] = d[1]
        d[2] = d[0]
        d[0] = 0
        d[1] = 0
      of 3, 4:
        if not s[2]:
          d[2] -= d[0]
        if not s[3]:
          d[3] -= d[1]
      else:
        discard
      t.setLen(0)
      for f in d:
        t.add(fmt("{f:g}, "))
      t.setlen(t.len - 2)
      entry.setText(t)
      (pda.dataX, pda.dataY, pda.dataWidth, pda.dataHeight) = d # (d[0], d[1], 
d[2], d[3])
      pda.fullScale = min(pda.darea.allocatedWidth.float / pda.dataWidth, 
pda.darea.allocatedHeight.float / pda.dataHeight)
      updateAdjustments(pda, 0, 0)
      pda.paint
    
    
    Run

Reply via email to