Page 1 of 1

A versatile clipboard

Posted: Fri May 17, 2019 9:28 am
by Henko
Reading about the problem with the clipboard in the "bug reports" section, i came to design and code a versatile clipboard, based on the "dictionary" file type developed not long ago.

If the programmer wants to store a collection of data for later use, or use in another program, he packes the data in a single string (called a "package"), gives it a short key, and store the package with its key on the clipboard.
When needed, he can retrieve the package using the key, leaving it on the clipboard, or delete it there, and use the SPLIT command to unpack the package into the original data.

In the first version hereafter, there are 3 commands :

clip_board$ ("+",key$,package$) -> store the package on the clipboard
package$ = clip_board$ ("=",key$,"") -> retrieve a package and leave it
package$ = clip_board$ ("-",key$,"") -> retrieve a package and delete it

Initialization of the clipboard is automatic, as is the storage capacity.

Maybe there are suggestions for additional clipboard functions?

Code: Select all

' test program for clipboard function
'
option base 1
clip_board$("+","single_var","12345")  ' single value to clipboard
print clip_board$("=","single_var","") ' print it

a$="monday" ! b$="tuesday"  ' package with 2 strings to clipboard
pack$ = a$ & "," & b$
clip_board$("+","2str",pack$)

ret$ = clip_board$("=","2str","") ' retrieve and print it
if ret$ ="not found" then ! print ret$ ! stop ! end if
split ret$ to m$,n with ","
print m$(1),m$(2)
end

' versatile clipboard, version may 17, 2019
' using the "dictionary" file type
' self initializing, dynamic sizing
' package$ = collection of data, packed into a string
'            by the application programmer
' key$     = key under which the packaged can be retrieved
' opcode$  = action to be performed:
'            "+" = store the package on the clipboard
'            "=" = retrieve the package and leave it
'            "-" = retrieve the package and delete it
'
def clip_board$(opcode$,key$,package$)
changed=0 ! a$=""
if init=0 then
  init=1 ! table$("init","","clipboard.data")
  end if
if opcode$="+" then
  table$("add",key$,package$) ! changed=1
  end if
if opcode$="=" then return table$("get",key$,"")
if opcode$="-" then
  a$=table$("get",key$,"") ! table$("del",key$,"") ! changed=1
  end if
if changed then table$("save","","")
if a$<>"" then return a$
end def

{dictionary}

Re: A versatile clipboard

Posted: Fri May 17, 2019 4:10 pm
by Henko
Another example: a personnel record with mixed variable types.
The (simulated) record is put on the cliboard by one program:

Code: Select all

' test program for clipboard function
'
option base 1

' *** personnel record, needed by some (query) application ***
key$="clint_p"
name$="Clinton"
surname$="Peacock"
birthdate$="11-23-1985"
dept$="R&D-dept."
salary=40000
sales_last_year=217000

' *** package it and put it on the clipboard ***
p$ = name$ & "," & surname$ & "," & birthdate$ & ","
p$ &= dept$ & "," & salary & "," & sales_last_year
clip_board$("+",key$,p$)
end

{clipboard.libr}
And retrieved by another program:

Code: Select all

option base 1
' *** retrieve the record, unpack and print
pers$=clip_board$("=","clint_p","")
split pers$ to m$,n with ","
for i=1 to n ! print m$(i) ! next i
end

{clipboard.libr}
For convenience here are the include files.

"Clipboard.libr" :

Code: Select all

' versatile clipboard, version may 17, 2019
' using the "dictionary" file type
' self initializing, dynamic sizing
' package$ = collection of data, packed into a string
'            by the application programmer
' key$     = key under which the packaged can be retrieved
' opcode$  = action to be performed:
'            "+" = store the package on the clipboard
'            "=" = retrieve the package and leave it
'            "-" = retrieve the package and delete it
'
def clip_board$(opcode$,key$,package$)
changed=0 ! a$=""
if init=0 then
  init=1 ! table$("init","","clipboard.data")
  end if
if opcode$="+" then
  table$("add",key$,package$) ! changed=1
  end if
if opcode$="=" then return table$("get",key$,"")
if opcode$="-" then
  a$=table$("get",key$,"") ! table$("del",key$,"") ! changed=1
  end if
if changed then table$("save","","")
if a$<>"" then return a$
end def

{dictionary.libr}
and "dictionary.libr" :

Code: Select all

' pseudo associative array for sB (version april 21, 2019)
'
def table$(opcode$,key$,content$)
if opcode$="init" then
  .f$=content$
  if file_exists(.f$) then ! load_array(.f$) ! return "" ! end if
  N=64 ! .Ntab=N ! dim keys$(N),contents$(N) ! return ""
  end if
if opcode$="add" then
  for i=1 to N
    if keys$(i)=key$ then return "key exists"
    next i
  adr=find("")
  if adr=0 then ! adr=N+1 ! N=expand() ! end if
  keys$(adr)=key$ ! contents$(adr)=content$ ! return ""
  end if
if opcode$="get" then
  adr=find(key$) ! if adr=0 then return "not found"
  return contents$(adr)
  end if
if opcode$="replace" then
  adr=find(key$) ! if adr=0 then return "not found"
  contents$(adr)=content$ ! return ""
  end if
if opcode$="del" then
  adr=find(key$) ! if adr=0 then return "not found"
  keys$(adr)="" ! return ""
  end if
if opcode$="count" then
  num=0
  for i=1 to N ! if keys$(i)<>"" then num+=1 ! next i
  return num
  end if
if opcode$="save" then ! save_array(.f$) ! return "" ! end if
return "unknown opcode"
end def

def load_array(f$)
file f$ input .Ntab ! table$.N=.Ntab
dim table$.keys$(.Ntab),table$.contents$(.Ntab)
for i=1 to .Ntab
  file f$ input table$.keys$(i),table$.contents$(i)
  next i
end def

def save_array(f$)
if f$="" then return "nothing saved"
if file_exists(f$) then file f$ delete
file f$ print .Ntab
for i=1 to .Ntab
  if table$.keys$(i)="" then ! file f$ print """""",""""""
    else ! file f$ print table$.keys$(i),table$.contents$(i)
    end if
  next i
.array_changed=0
end def

def expand()
n=int(1.5*.Ntab)
dim a$(n),b$(n)
for i=1 to .Ntab
  a$(i)=table$.keys$(i) ! b$(i)=table$.contents$(i)
  next i
dim table$.keys$(n),table$.contents$(n)
for i=1 to .Ntab
  table$.keys$(i)=a$(i) ! table$.contents$(i)=b$(i)
  next i
.Ntab=n ! return n
end def

def find(k$)
for i=1 to .Ntab ! if table$.keys$(i)=k$ then break ! next i
if i<=.Ntab then return i else return 0
end def

Re: A versatile clipboard

Posted: Mon May 20, 2019 7:05 am
by GeorgeMcGinn
In the Weatherman App I am writing that calls (runs) multiple programs, this is exactly how I use the CLIPBOARD — I create a message string and then use the SPLIT after reading it to separate the fields into their variables, exactly like your code.

I think I mentioned in the other post that numeric values must be strings (with quotes).

I was looking into seeing if I could create a DATA statement and instead of doing a SPLIT, I would do a READ directly into the variable name, removing the extra steps in splitting it into an array then looping through the array again to move it into each variable.

Haven’t gotten that far yet.

I have some bad news to report, I had to upgrade my iPad from 10.3.3 to 12.3 because a lot of my programs/apps for other programming languages and other things that I use apps for have stopped working or I was unable to upload them or even some of the new apps that I wanted to get high needed to have 11.0 or higher. So looks like I will be running SmartBASIC just like everybody else, with the issues and problems it has due to the new operating system.


Henko wrote:
Fri May 17, 2019 4:10 pm
Another example: a personnel record with mixed variable types.
The (simulated) record is put on the cliboard by one program:

Code: Select all

' test program for clipboard function
'
option base 1

' *** personnel record, needed by some (query) application ***
key$="clint_p"
name$="Clinton"
surname$="Peacock"
birthdate$="11-23-1985"
dept$="R&D-dept."
salary=40000
sales_last_year=217000

' *** package it and put it on the clipboard ***
p$ = name$ & "," & surname$ & "," & birthdate$ & ","
p$ &= dept$ & "," & salary & "," & sales_last_year
clip_board$("+",key$,p$)
end

{clipboard.libr}
And retrieved by another program:

Code: Select all

option base 1
' *** retrieve the record, unpack and print
pers$=clip_board$("=","clint_p","")
split pers$ to m$,n with ","
for i=1 to n ! print m$(i) ! next i
end

{clipboard.libr}
For convenience here are the include files.

"Clipboard.libr" :

Code: Select all

' versatile clipboard, version may 17, 2019
' using the "dictionary" file type
' self initializing, dynamic sizing
' package$ = collection of data, packed into a string
'            by the application programmer
' key$     = key under which the packaged can be retrieved
' opcode$  = action to be performed:
'            "+" = store the package on the clipboard
'            "=" = retrieve the package and leave it
'            "-" = retrieve the package and delete it
'
def clip_board$(opcode$,key$,package$)
changed=0 ! a$=""
if init=0 then
  init=1 ! table$("init","","clipboard.data")
  end if
if opcode$="+" then
  table$("add",key$,package$) ! changed=1
  end if
if opcode$="=" then return table$("get",key$,"")
if opcode$="-" then
  a$=table$("get",key$,"") ! table$("del",key$,"") ! changed=1
  end if
if changed then table$("save","","")
if a$<>"" then return a$
end def

{dictionary.libr}
and "dictionary.libr" :

Code: Select all

' pseudo associative array for sB (version april 21, 2019)
'
def table$(opcode$,key$,content$)
if opcode$="init" then
  .f$=content$
  if file_exists(.f$) then ! load_array(.f$) ! return "" ! end if
  N=64 ! .Ntab=N ! dim keys$(N),contents$(N) ! return ""
  end if
if opcode$="add" then
  for i=1 to N
    if keys$(i)=key$ then return "key exists"
    next i
  adr=find("")
  if adr=0 then ! adr=N+1 ! N=expand() ! end if
  keys$(adr)=key$ ! contents$(adr)=content$ ! return ""
  end if
if opcode$="get" then
  adr=find(key$) ! if adr=0 then return "not found"
  return contents$(adr)
  end if
if opcode$="replace" then
  adr=find(key$) ! if adr=0 then return "not found"
  contents$(adr)=content$ ! return ""
  end if
if opcode$="del" then
  adr=find(key$) ! if adr=0 then return "not found"
  keys$(adr)="" ! return ""
  end if
if opcode$="count" then
  num=0
  for i=1 to N ! if keys$(i)<>"" then num+=1 ! next i
  return num
  end if
if opcode$="save" then ! save_array(.f$) ! return "" ! end if
return "unknown opcode"
end def

def load_array(f$)
file f$ input .Ntab ! table$.N=.Ntab
dim table$.keys$(.Ntab),table$.contents$(.Ntab)
for i=1 to .Ntab
  file f$ input table$.keys$(i),table$.contents$(i)
  next i
end def

def save_array(f$)
if f$="" then return "nothing saved"
if file_exists(f$) then file f$ delete
file f$ print .Ntab
for i=1 to .Ntab
  if table$.keys$(i)="" then ! file f$ print """""",""""""
    else ! file f$ print table$.keys$(i),table$.contents$(i)
    end if
  next i
.array_changed=0
end def

def expand()
n=int(1.5*.Ntab)
dim a$(n),b$(n)
for i=1 to .Ntab
  a$(i)=table$.keys$(i) ! b$(i)=table$.contents$(i)
  next i
dim table$.keys$(n),table$.contents$(n)
for i=1 to .Ntab
  table$.keys$(i)=a$(i) ! table$.contents$(i)=b$(i)
  next i
.Ntab=n ! return n
end def

def find(k$)
for i=1 to .Ntab ! if table$.keys$(i)=k$ then break ! next i
if i<=.Ntab then return i else return 0
end def

Re: A versatile clipboard

Posted: Mon May 20, 2019 7:29 am
by Henko
I think I mentioned in the other post that numeric values must be strings (with quotes).

I was looking into seeing if I could create a DATA statement and instead of doing a SPLIT, I would do a READ directly into the variable name, removing the extra steps in splitting it into an array then looping through the array again to move it into each variable.
Quotes are not needed when packing data in a string (one of the " smart" features of sB).
But after the SPLIT the VAL() function is needed if you need the value of the variable.

Creating a READ / DATA construct is an interesting thought, but it implies modifying the sB program during runtime. Would be fun :o

Re: A versatile clipboard

Posted: Mon May 20, 2019 2:41 pm
by GeorgeMcGinn
Henko wrote:
Mon May 20, 2019 7:29 am
. . .
Creating a READ / DATA construct is an interesting thought, but it implies modifying the sB program during runtime. Would be fun :o
I think so (since I built my own computer from a Raspberry PI, the Systems Programmer in me is coming back out)