I've got the answer to the CharSetID=0.

I bet you would never guess it. ;-) Some very analytic mind (Sherlock H.?) would be needed to guess the correct answer without having access to my database.
To cut it short: our application had a local "DUAL" table in it's schema. PL/SQL Developer get's the characterset most probably by a "SELECT USERENV('LANGUAGE') FROM DUAL" or similiar query and if the "DUAL" table has no rows in it, the query would return no rows either.
All my characterset problems with PLSD came from this. Here's how I used to make a copy of the application (in a schema):
1. export tables from source schema
2. export table definitions from source schema
3. create new user (dest. schema)
4. create the empty tables in dest. schema
5. disable all constraints on all tables
6. import data
7. enable all constraints on all tables
The problem is between step 4. and 6. In step 4 an empty DUAL table was created in the application schema and every new connection in PLSD before step 6 resulted in a CharSetID=0 since the DUAL table was empty. And I did the table imports with such a new connection too ... thus the imported unicode data in the dest. schema became crap.
Conclusion:
a.) some "dumb" guy thought a DUAL table in the application schema would be OK (and in fact it is ... but only as long it has a single row in it ... no more, no less)
b.) always expect the unexpected
I doubt you'd change any line of code in PLSD only to come up for such a special case ... but you could easily fix it by changing every reference to the DUAL table to SYS.DUAL (thus specifying the schema too). This way it could not use a DUAL table in the given schema that we are logging into ... not even by accident.
PS: I've dropped that DUAL table quickly

since it was only there for some Oracle 8i hack and we've migrated to 9i long ago.