Hi Geoff, I didn't know either, that GetTextInRect removed non visible characters such as tabs. I've done some testing, & found some interesting anomalies, in the way Jaws *sees* tab characters, & likely other non visible characters. In wordPad, if you type a couple of words, hit the tab key to insert the tab character, another couple of words & the tab again, another word or 2, then: 1. hit home to move the PC cursor back to the beginning of the line, then arrow across to where you placed the tabs, then Jaws recognises the tabs & announces them as expected, & says 9 on a triple hit of numpad5. 2. change to the invisible cursor, & place it at the beginning of the line. On repeating the above reading, the tabs are not recognised, & Jaws sees them as character 0. * Very strange indeed * Conclusion. Make sure that when you are using a script/function to pick up text where tabs etc are required in that text, that the type of cursor that is active during the pick up, is able to *see* the tabs. * I was not able to get the GetTextInRect function, to pick up tab characters with any cursor active, or with any manipulation of that functions parameters. I also looked for other functions that may be suitable for your purpose, but none seem able to get blocks of text from an emulator screen. You may like to try placing a cursor on a line, in that set of lines, then using GetChunk () & see if it will pick up the whole group of lines including the tab characters. I use GetChunk () extensively in my emulator scripts, & it can yield some unexpected, & sometimes very useful results. Failing that, below is a function which may do what you want. It involves the inelegant running about of the invisible cursor that you aluded to, to repeatedly call GetLine () to accumulate the information from the group of lines. It presumes that as well as seperating the individual items with tab characters, that there is either a tab character at the end of each line, or at the beginning of the next line, such that the last item on the first line is seperated by a tab from the first item on the next line when the lines are concatenated together. If not, then unrem the additional script line as indicated. By doing this in a seperate function, it keeps your original script for doing the task uncluttered as in my guesswork demo. Just substitute the actual values for my sample ones in the call to GetTextBlock. The first parameter is the X pixel coordinate somewhere on the first line to be picked up, the second is a Y coordinate, & the third parameter is the number of lines you want to pick up with Getline(). Note: below the demo script, is the .jsd entry for the function in case you aren't familiar with page 2 of the control+I dialog. If required, just cut & paste it into your .jsd file inside the script manager, save with control+W, exit & restart the script manager before compiling. String Function GetTextBlock (int StartPosX, int StartPosY, int NumberOfLines) VAR INT Count, STRING ReturnString SaveCursor () ; saves which cursor was active when this function was called InvisibleCursor () SaveCursor () ;saves the position of the invisible cursor so it will be returned there when the function exits MoveTo (StartPosX, StartPosY) ; move the invisible cursor to somewhere on the top line LET Count = 1 While (Count <= NumberOfLines) LET ReturnString = ReturnString + GetLine () ; unrem the next line if the application does not provide a "\9" at the end or beginning of a line ; LET ReturnString = ReturnString + "\9" NextLine () LET Count = Count + 1 EndWhile RETURN (ReturnString) EndFunction Script TestOnF8 () var string StringVar, string AnnounceString, string VirtualShowString let StringVar = GetTextBlock (174, 84, 3) ; this will read ok if the tab character immediately follows a text item without any intervening spaces ; note that the tab is replaced by a period & 2 spaces as in normal sentences let AnnounceString = StringReplaceSubstrings (StringVar, "\9", ". ") ; here, the tabs are replaced by the line feed character, \N, in Jaws. let VirtualShowString = StringReplaceSubstrings (StringVar, "\9", "\N") if IsSameScript () then ; replace the below line with your way of displaying the user buffer SayMessage (OT_User_Buffer, VirtualShowString) ELSE ; hit once ; replace the below line with your way of saying a string SayString (AnnounceString) EndIf ; key hit once or more EndScript .jsd entry. :function GetTextBlock :Returns string the block of text :Param int/StartPosX the X pixel position for the first line to be read :Param int/StartPosY the Y pixel position for the first line to be read :Param int/NumberOfLines the number of lines to be read including the first Regards, Paul from Aust ----- Original Message ----- From: "Geoff personal" <gch@xxxxxxxxxxxxxxxx> Wow Paul and Donald! this is all just fantastic stuff for me! thank you thank you so much to both of you for your kind energies and efforts, and for providing invaluable example code here for me of these function usages. There's lots here I've never used, and it sounds like it'd be helpful for me to get to grips with all of this. What I've done today is firstly try Paul's approach, since I recieved it first. After some time, ... ok a lot of time, diddling with this, what it appears to me like is happening is, The GetTextInRect function I'm using to grab blocks of data from the screen, seems to me, somehow, to be actually AutoConverting the "\9" tab characters, to spaces in my string! Before the StringReplaceSubstrings function gets time to do it's stuff. So that by the time it does, there's no tabs left in the string to be found! is that possible? probible? Then, I thought that perhaps this GetTextInRect function, upon only recieving the 4 parameters of Left, top, right, and bottom, might feel it was being given permission to strip out Tabs automatically, because I wasn't asking it to keep lineBreaks as a whole block. But that's not it either, as when I fill in all 8 of the parameters, including a 1 at the end to retain LineBreaks, it still doesn't seem to work. So, when I follow Paul's logic, By the way I never ever knew that the tab character had a value of "\9", nor that spaces had one of "\32" before, But, thanks to this great coding help, I do now! so, as I say when I use paul's logic, and insert the word "Blonk. " in quotes where he previously had coded a period character, as I'd indicated I desired, just to make things reeeally clear to me, when I replace "\9", with "\32", like this: (Oh I've also altered Paul's example stringCode names a bit as well to suit, ;let sAnnouncePromptsWithPauses = StringReplaceSubstrings (sFunctionKeyPrompts, "\32", "Blonk. ") It's putting the word "Blonk" in my resultant string every single place it sees not only a space, (which of course appears sometimes between the wordings of the function Key options themselves, so is obviously quite non-optimal, but also whenever it sees the Tab delimiters! Which is just so weird! So it thinks they're spaces too! Has anyone ever encountered this before, and/or have any way around it such that the string gathering retains the tabs, with their character value of "\9", as is? I've just tested GetTextInFrame, and it does exactly the same thing! ooooh man! I've just clarified this even more, by discovering that when I use a GetLine instead, then Paul's logic works a treat! and the tabs or "\9" characters, seem to indeed be retained in the string, and thus found by the StringReplaceSubstrings, function! So one wonders now, why on earth would certain stringGathering functions feel it their duty/ungiven permission, to treat Tabs as spaces! <sigh.> So I guess I'll have to do reeeeally crude and slow stuf like Routing jaws Cursor to certain spots and doing GetLine, nextLine, GetLine stuff, which is just sooo inelegant! Any thoughts anyone? __________ Visit and contribute to The JAWS Script Repository http://jawsscripts.com View the list's information and change your settings at http://www.freelists.org/list/jawsscripts