FB II Compiler







Disk I/O














Made with FB


Put index$ content into the Clipboard

I have a number of entries in the zero index ID of the array INDEX$. I am trying to move that data to the clipboard with the following routine. No luck. Can anyone tell me why?

LOCAL FN TextBacktoClip
  scrapHndl& = FN ZEROSCRAP 'Clear the clipboard
  hndlSize& = MEM(_usedBytes) 'Get the size of INDEX$ array used
  TEXThndl& = FN NEWHANDLE(hndlSize&) 'Get a new handle
  indexAddress& = MEM(_indxAddr) ' Get address of INDEX$ array
  BLOCKMOVE indexAddress&,[TEXThndl&],hndlSize& 'Move INDEX$ data to new handle
  err = FN HLOCK(TEXThndl&)
  LONG IF err = _noErr
    scrapHndl& = FN PUTSCRAP (hndlSize&, _"TEXT", [TEXThndl&]) ' Put on clipboard
    err = FN HUNLOCK(TEXThndl&)

The value created for hndlSize& seems consistent with the data in INDEX$ and I get a non-zero value for indexAddress& (I have no way of verifying if it is correct). With the routine as written I get garbage on the clipboard.

I move the INDEX$ data with the BLOCKMOVE instruction only to comply with the parameters of the FN PUTSCRAP function. Perhaps there is an easier way to do this (simply moving the data directly from the INDEX$ array) but I do not know how.

Dale Blackwell

There are two things to remember here, which might explain your strange results.

The first regards the number you're getting for hndlSize&. The number returned by MEM(_usedBytes) is definitely not equal to the sum of the lengths of the strings you've assigned to INDEX$ elements. It seems to be calculated in one or the other of the following ways, depending on how you allocated memory for the INDEX$:

* If you specified fixed-length strings (i.e., you used the syntax "CLEAR numElements&, 0, maxLength"), then MEM(_usedBytes) returns this number:

(n + 1) * maxLength

where n is the number of the highest index element that you've actually assigned a string to (even if it was a null string).

* If you specified variable-length strings (i.e., you used the syntax "CLEAR numBytes& [,0]"), then MEM(_usedBytes) returns this number:

(n + 1) + s

where n is defined as before, and s is the sum of the lengths of the strings you've assigned.

The second thing to note is that the way strings are formatted in an INDEX$ array is not the same way that text is formatted on the clipboard, so that if you do a straight memory copy (as you were doing), you'll get garbage. Possibly two kinds of garbage:

* Every string element in an INDEX$ array is preceded by a length byte, while text on the clipboard has no length bytes. When you do the PUTSCRAP, you're copying all those length bytes to the clipboard, where they get displayed as if they were a normal part of the text.

* If you're using fixed-length INDEX$ elements, then in addition to the length-byte problem, you have the trailing-garbage problem. For example, say you've specified a fixed (max) length of 50 bytes for your INDEX$ elements, and then you do this:

INDEX$(0) = "Rick"
INDEX$(1) = "Brown"

Now MEM(_usedBytes) returns 100 (50 bytes for element #0, and 50 for element #1). The first 50 bytes consists of: CHR$(4) (the length byte), followed by "Rick", followed by 45 bytes of God-knows-what. Likewise, the second 50 bytes consists of: CHR$(5), followed by "Brown", followed by 44 bytes of garbage. If you PUTSCRAP these 100 bytes, then you get mostly garbage on the clipboard.

It sounds like maybe what you want is to put each INDEX$ element onto a separate line of text in the clipboard. In that case the consecutive elements of text should be separated by an ASCII character 13 (a carriage-return character) on the clipboard. There should be _no_ length bytes. This probably means you'll have to copy things element-by-element rather than doing a single move of the whole lot. I would do it like this (warning: untested):

scrapHndl& = FN ZEROSCRAP 'Clear the clipboard
ptrSize& = MEM(_usedBytes)
'(MEM(_usedBytes) is "at least" as much space as we need--
'we may not need all of it.)

'Get a pointer rather than a handle (more efficient if
'we never intend to let the block move anyway):
TEXTptr& = FN NEWPTR(ptrSize&)
  offset& = 0
  idxStart& = MEM(_indxAddr)
  numElements = MEM(_numElem)
  FOR i = 0 TO numElements
    temp$ = INDEX$(i)
    lngth = LEN(temp$)
    IF lngth THEN BLOCKMOVE @temp$ + 1, TEXTptr& + offset&, lngth
    POKE TEXTptr& + offset& + lngth, 13 'Add CR character to end
    offset& = offset& + lngth + 1
'offset& now equals # of bytes we moved. Put them on clipboard:
  numBytes& = offset&
  scrapHndl& = FN PUTSCRAP (numBytes&, _"TEXT", TEXTptr&)
'[couldn't assign TEXTptr&: handle error here]