FB II Compiler

PG PRO

Debugging

Memory

System

Mathematics

Resources

Disk I/O

Windows

Controls

Menus

Mouse

Keyboard

Text

Fonts

Drawing

Sound

Clipboard

Printing

Communication

ASM

Made with FB

RESOURCES

Emulate GetIndStr for CODE resources


The STR# function in FB does what you want. Look at page 295 in the FB II Reference manual. If you're working with STR# resources, you should also check the FB II Reference Manual for DEF APPNDSTR and DEF REMOVESTR
Al Staffieri Jr

It turns out, though, that the FB str# function will not compile in a code resource. So I still need the trap word, if anyone has it.
Wave

- There is no trap word. GetIndString is one of those highly annoying Toolbox calls that don't actually exist.

Well, OK, they do exist - but not like normal calls do. Instead of providing a trap word or selector to call code living in the System file, Apple provides a precompiled library containing the actual code. So GetIndString does not live in the OS - it lives in your application.

Since FutureBASIC doesn't really have a linker, it can't link in a compiled library. And thus the only solution is to write the function over from scratch.

If you have CodeWarrior and know assembly language, you can use the built - in disassembler to look at the MacOS Lib. Use the Find tool to jump to the trap you want, then copy & paste the listing. It'll take some tweaking, but it works.

Mars

Here is what I would do to mimic GetIndStr. I tested it with the STR# error resource in PG and it seemed to work, though I guess it could be improved (maybe there is a way to avoid loading the whole resource in memory, and second, I'm sure someone would say something about RELEASERESOURCE).
CLEAR LOCAL MODE
  DIM hndl&,offset&,theSTR$,i%

LOCAL FN GetIndSTR$(resID,elem)
  hndl& = FN GETRESOURCE(_"STR#",resID)
  LONG IF hndl&
    LONG IF elem>0 AND elem< = {[hndl&]} 
'valid range for elem? (1st word in handle holds num of strings in STR#)
      FOR i = 1 TO elem 'loop to reach the String we want 
        LONG IF i = 1 '1st elem we need to skip the num of strings
          offset& = 2 
        XELSE
'otherwise add to offset the previous offset,
'the length of the previous string and 1 for the length byte
         offset& =  offset& + PEEK([hndl&] + offset&) + 1
        END IF
      NEXT
      theSTR$ = PSTR$([hndl&] + offset&)
'get the pascal string at offset
'I guess PSTR$ works for code, if not use BLOCKMOVE instead
    END IF
    CALL RELEASERESOURCE(hndl&)
  END IF
END FN = theSTR$
Alain

I enjoyed Pontus' ingenious assembly code for getting a string from a handle, but found it curiously difficult to understand. In the course of interpreting it, I learned much about the structure of STR# resources. The rewritten version of FN RetrieveStringFromHandle given below does not work any better (except for one improvement), but uses comments, labels, branch instructions and dbra loops, for greater comprehensibility. The improvement is that this version returns a null string if you inadvertently call it with IStr% <= 0, instead of returning random garble.
LOCAL MODE
LOCAL FN RetrieveStringFromHandle (ResH&, IStr%, StrPtr&)
 `       move.l ^ResH&,a0
 `       move.l (a0),a0     ; de-reference handle
 `       move.l ^StrPtr&,a1 ; pointer to returned string
 `       move.w ^IStr%,d1   ; wanted string number in resource
 `       beq.s   null       ; there is no string #0
 `       bmi.s   null       ; there are no strings #negative
 `       cmp.w  (a0)+,d1    ; compare numStrings with requested
 `       bgt.s   null       ; branch if there are not enough

 `       clr.l   d0         ; prepare d0 for address calculations
 `       subq.w  #2,d1
 `       bmi.s   mve        ; if we wanted string #1, go get it
 `nxtstr move.b (a0)+,d0    ; get length, and incr a0 by 1 byte
 `       adda.l  d0,a0      ; add length to a0 to skip this string
 `       dbra    d1,nxtstr  ; loop until we get to the wanted string

 `mve    move.b (a0),d0     ; length to d0 for loop count
 `mloop  move.b (a0)+,(a1)+ ; copy length byte and characters
 `       dbra   d0,mloop    ; loop until all chars copied
 `       bra.s  exit

 `null   clr.b  (a1)        ; set length byte to zero
 `exit
END FN

CLEAR LOCAL MODE
LOCAL FN Get1String$ (ResID%, IStr%)
 DIM ResH&, TheString$
 ResH& = FN GET1RESOURCE(_"STR#", ResID%)
 LONG IF ResH&
  FN RetrieveStringFromHandle (ResH&, IStr%, @TheString$)
 END IF
END FN = TheString$

Robert