2 Replies Latest reply on Jul 15, 2009 2:04 AM by [Jongware]

    Idiots Guide to Replacing Special Characters

    jeffmlevy Level 1

      In Short:


      Can someone please send me in the direction of an idiots guide to replacing special characters in InDesign?


      In Detail:


      I've got sevaral text strings which are being inserted via '.changeTo()' -- my strings substitute beautifully. What's failing, obviously, is when a user types in a special character, in this case, a ©. My preprocessor sends the escaped form of this string, © directly to indesign, and indesign faithfully leaves that text in there.


      In my template, I'd have something like: [[copyright]] ... I use the [[ and ]] as simple points of reference for my findWhat/changeText function calls. IE: [[copyright]] would be replaced with user input: "&copy my Company 2009 - All Rights Reserved" ...


      Well, what I'm trying to avoid, is changing all of my text in my preprocessor. I have found success in doing a simple str_replace of &copy (or even the unicode \u00A9), something akin to: str_replace('\u00A9', '^2', $text) - - and then InDesign does indeed turn that into a © symbol.


      I'm sure the problem becomes quite evident. I can't (and shouldn't) build a reference list of all unicode chars and their respective ^ equivalent... Clearly I'm missing something quite basic here.


      First, what's the correct way of doing this? My source string (the string data I'm sending to InDesign) can provide either the HTML equivalent (&copy), or the unicode. Either is fine by me, I don't care.


      But how to get InDesign to translate the characters for me? I don't want literal © showing up in my string after a render is complete


      Any help in this would be greatly appreciated.

        • 1. Re: Idiots Guide to Replacing Special Characters
          [Jongware] Most Valuable Participant

          How about a GREP to search for angle brackets with a Unicode value inbetween?


          app.findGrepPreferences.findWhat = "\<[0-9A-F][0-9A-F][0-9A-F][0-9A-F]\>";

          myFoundItems = app.activeDocument.findGrep(true);     // "true" is important here!


          Now 'myFoundItems' holds an array of pointers into the document to the locations of all found texts. Iterate over them to translate them one by one into 'real' characters:


          for (i=0; i<myFoundItems.length; i++)

             result = myFoundItems[i].contents;

          .. 'result' will now hold "<00A9>" .. checking a Javascript manual, please wait ..


          fromCharCode()Takes the specified Unicode values and returns a string



          The argument is a number, and we have it in hexadecimal. Let's get a regular decimal value -- "parseInt" will do that. We also need to chop off the first "<" (the last one is ignored by parseInt).


          value = result.parseInt (result.substr(1));


          .. and write it back into the document as a Unicode character:


          myFoundItems[j].contents = String.fromCharCode(value);

          } // end loop


          Untested, but the main idea should be clear.

          • 2. Re: Idiots Guide to Replacing Special Characters
            [Jongware] Most Valuable Participant

            D'oh -- I should'of tested it first! There were lots and lots of errors in those 8 lines.


            This should work a bit better (at least, it did when I tested it):


            app.findGrepPreferences.findWhat = "(?i)<[0-9A-F][0-9A-F][0-9A-F][0-9A-F]>";
            myFoundItems = app.activeDocument.findGrep(true);
            for (i=0; i<myFoundItems.length; i++)
             result = myFoundItems[i].contents;
             value = parseInt (result.substr(1,4),16);
             myFoundItems[i].contents = String.fromCharCode(value);
            } // end loop


            A few of the more salient errors (for your amusement, no doubt):

            • "\<[0-9A-F][0-9A-F][0-9A-F][0-9A-F]\>" is not a valid GREP string, '<' and '>' should not be escaped (and if they had to, I'd had to type two backslashes in javascript!). Added 'ignore case' because it failed in my test on <00a9> and I did not see why.
            • parseInt is a global function, no part of 'result'
            • parseInt does recalculate hex to decimal, but you have to actually state the base number 16 somewhere ...
            • parseInt fails when encountering a non-hexadecimal character -- rather, it returns garbage. That happens when you feed it "00A9>"; last char needs chopping off as swell.
            • myFoundItems[j].contents: the most stoopid error. And again I failed to notice it rite-away.