Prev: REVLIST Command HP 48G
Next: RPN/RPL Calculator implementations, list of, regular post [long,FAQ]
From: Jacob Wall on 5 May 2010 00:55 Hello, I am thinking about adding a language option to a larger library with many labels, messages, etc. and so far my options that I've thought of don't look that great. A few scenarios I've considered: 1. Have separate Debug4x projects for the "same" library, one for each language. The headaches involved with upkeeping each project separately renders this scenario basically out of the question. 2. Each time in the code when a string is required, check a language setting variable and provide the correct string. Doable, but there's gotta be a better way. 3. Debug4x message tables? Can't figure out how to make this work with conditionals, ie same as No. 2, using a language setting variable, to use different message tables to pull messages from. So, No. 1 above, as much of a headache as it would be to upkeep, would be superior in memory and speed efficiency during operation. No. 2 would obviously be easier to maintain but the library would grow in size, almost unnecessarily it would seem as most users I believe would only require one language, and also would slow down operation, although not noticeably if only a single string were called but in a case were multiple strings were needed it could become noticeable. No. 3, I suppose creating separate libraries with just the messages might work, then the user could install only the language library desired. Maybe give each of the message libraries created the same number so only one could be installed at a time so that in the main library you would always call the same #xxxxx JstGETTHEMSG, and a check for the required message library would only mean checking for one. I have not experimented with any of the options yet, basically realize it would be a little bit of work so may as well look into it a little, hopefully get some input from others who have done something like this before I get too carried away with an inefficient approach. Any thoughts? Ideas would be appreciated. Jacob
From: Andreas Möller on 5 May 2010 04:55 Hello, > Any thoughts? Ideas would be appreciated. This can be accomplished easily in several ways. Two ways are possible for you. First: A mixture of No. 1 and No. 3: a) separate all your messages into a separate source file. ( If you are using the inform box editor make sure that the checkmark in front of M table is *clear* as we will not using the inform box editor message table functions. Instead use placeholders for all you message without a space, e.g. Label_with_text. We will then use defines to call these messages from the message table of the lib. That way we have total control over our messages. If you need this, then contact me by private mail as this needs a rather lengthy explanation and can be easiest explained through some source file examples. ) b) After that create a *.hpp project for each language you desire, it would contain at least two source files, e.g. ProgramCode.s and another one for your languages so that you have a clean separation between your actual program code and the messages you wish to use. As an example you would have an English.hpp project containing ProgramCode.s and MessagesEnglish.s and a German.hpp project containing ProgramCode.s and MessagesGerman.s. In the 'Project Window' in the 'Project Data' tab in the field 'Message' you can specify which messages will be used for your library. Put in the name of your Library Message Entry, for example MyMessages. c) Now in all your source files for your messages, here MessagesEnglish.s and MessagesGerman.s you will create the Library Message Entry by using this code: ASSEMBLE = MyMessages RPL ARRY ( or LNKARRY if you prefer ) [ "First Message" "Second Message" "Third Message" "and so on" ] Of course you will use your English messages in MessagesEnglish.s and of course you will use your German messages in MessagesGerman.s ;-) d) Accessing the messages: In your program source file, in this example ProgramCode.s put the following macros at the beginning of your file *before* your first xNAME or NULLNAME depending on whether you want to use traditional SASM syntax or MASD syntax: SASM syntax: ASSEMBLE DOMSG MACRO * romid,msgnr * Macro, to handle msg nr. generation CON(5) =DOBINT CON(5) ($1)*256+($2) DOMSG ENDM RPL MASD syntax: * Count for the Message Table ASSEMBLEM DC RomIdx256 100*RomId !RPL ( 100h = 256d ) In both 'RomId' is fetched from the library number that you use and which is the number you have given the field RomId in the 'Project Window' in the 'Project Data' tab. Now if you want to access a message in your source file you will use the following construct depending on whether you want to use traditional SASM syntax or MASD syntax: SASM syntax: ASSEMBLE DOMSG RomId,1 ( #BINT for your first message ) RPL ASSEMBLE DOMSG RomId,2 ( #BINT for your second message ) RPL ASSEMBLE DOMSG RomId,3 ( #BINT for your third message ) RPL MASD syntax: ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#1 !RPL ( #BINT for your first message ) ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#2 !RPL ( #BINT for your second message ) ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#3 !RPL ( #BINT for your third message ) Of course you might want to call JstGETTHEMSG afterwards depending on what you need (The menu and the POL and some other built-in stuff can work directly with #MessageBINTs). Note that you can use conditional assembly for this, too. But the above is a lot easier to handle then to fiddle with the parameters for conditional assembly in debug4x and that is the reason I omit it here. Second: No. 2 Usually the message table pointer of a library ( which is stored in the ROMPTAB of the calculator ) points to the Library Message Entry you provide. But this pointer can point anywhere. If you want multiple message tables ( which would be equal to using more than 255 (FFh) messages ) you can hot switch to another message table by changing this pointer to any NULLNAME of your lib where your additional messages are stored in an array. To access a single message of each table use the same mechanism as described in the first solution. Be aware that, for example, JstGETTHEMSG fetches the messages from the current active message table that is stored in the ROMPTAB. To exchange the message table pointer in the ROMPTAB ( to enable hot switching ) you need some Saturn assembly code and also you might consider storing the pointers of the different messages tables in some reserved RAM areas while your program is running for faster access / switching. I suggest that you use the first solution I mentioned as this is easier to code and as most likely libraries do not contain more than 255 (FFh) messages. Also this has the benefit, as you mentioned, that the binary is smaller as it contains only the messages of the desired language. Maintaining is easy as you have the same program code for all projects and a specific language file. Just compile each project to a unique binary ( example: TreeBrowserEN, TreeBrowserDE ) and there you go. HTH, Andreas http://www.software49g.gmxhome.de
From: Jacob Wall on 5 May 2010 20:01 On 05/05/2010 1:55 AM, Andreas M�ller wrote: > Hello, > >> Any thoughts? Ideas would be appreciated. > This can be accomplished easily in several ways. > > Two ways are possible for you. > > First: A mixture of No. 1 and No. 3: > a) separate all your messages into a separate source file. > ( If you are using the inform box editor make sure that the checkmark > in front of M table is *clear* as we will not using the inform box > editor message table functions. Instead use placeholders for all you > message without a space, e.g. Label_with_text. We will then use > defines to call these messages from the message table of the lib. That > way we have total control over our messages. If you need this, then > contact me by private mail as this needs a rather lengthy explanation > and can be easiest explained through some source file examples. ) > > b) After that create a *.hpp project for each language you desire, it > would contain at least two source files, e.g. ProgramCode.s and > another one for your languages so that you have a clean separation > between your actual program code and the messages you wish to use. > As an example you would have an English.hpp project containing > ProgramCode.s and MessagesEnglish.s and a German.hpp project > containing ProgramCode.s and MessagesGerman.s. > > In the 'Project Window' in the 'Project Data' tab in the field > 'Message' you can specify which messages will be used for your > library. Put in the name of your Library Message Entry, for example > MyMessages. > > c) Now in all your source files for your messages, here > MessagesEnglish.s and MessagesGerman.s you will create the Library > Message Entry by using this code: > > ASSEMBLE > = MyMessages > RPL > ARRY ( or LNKARRY if you prefer ) > [ > "First Message" > "Second Message" > "Third Message" > "and so on" > ] > > Of course you will use your English messages in MessagesEnglish.s and > of course you will use your German messages in MessagesGerman.s ;-) > > d) Accessing the messages: In your program source file, in this > example ProgramCode.s put the following macros at the beginning of > your file *before* your first xNAME or NULLNAME depending on whether > you want to use traditional SASM syntax or MASD syntax: > > SASM syntax: > ASSEMBLE > DOMSG MACRO * romid,msgnr * Macro, to handle msg nr. generation > CON(5) =DOBINT > CON(5) ($1)*256+($2) > DOMSG ENDM > RPL > > MASD syntax: > * Count for the Message Table > ASSEMBLEM DC RomIdx256 100*RomId !RPL ( 100h = 256d ) > > In both 'RomId' is fetched from the library number that you use and > which is the number you have given the field RomId in the 'Project > Window' in the 'Project Data' tab. > > Now if you want to access a message in your source file you will use > the following construct depending on whether you want to use > traditional SASM syntax or MASD syntax: > > SASM syntax: > ASSEMBLE > DOMSG RomId,1 ( #BINT for your first message ) > RPL > > ASSEMBLE > DOMSG RomId,2 ( #BINT for your second message ) > RPL > > ASSEMBLE > DOMSG RomId,3 ( #BINT for your third message ) > RPL > > MASD syntax: > > ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#1 !RPL ( #BINT for your first > message ) > ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#2 !RPL ( #BINT for your second > message ) > ASSEMBLEM $(5)DOBINT $(5)RomIdx256+#3 !RPL ( #BINT for your third > message ) > > > Of course you might want to call JstGETTHEMSG afterwards depending on > what you need (The menu and the POL and some other built-in stuff can > work directly with #MessageBINTs). > > Note that you can use conditional assembly for this, too. But the > above is a lot easier to handle then to fiddle with the parameters for > conditional assembly in debug4x and that is the reason I omit it here. > > > > Second: No. 2 > Usually the message table pointer of a library ( which is stored in > the ROMPTAB of the calculator ) points to the Library Message Entry > you provide. But this pointer can point anywhere. If you want multiple > message tables ( which would be equal to using more than 255 (FFh) > messages ) you can hot switch to another message table by changing > this pointer to any NULLNAME of your lib where your additional > messages are stored in an array. To access a single message of each > table use the same mechanism as described in the first solution. Be > aware that, for example, JstGETTHEMSG fetches the messages from the > current active message table that is stored in the ROMPTAB. > To exchange the message table pointer in the ROMPTAB ( to enable hot > switching ) you need some Saturn assembly code and also you might > consider storing the pointers of the different messages tables in some > reserved RAM areas while your program is running for faster access / > switching. > > I suggest that you use the first solution I mentioned as this is > easier to code and as most likely libraries do not contain more than > 255 (FFh) messages. Also this has the benefit, as you mentioned, that > the binary is smaller as it contains only the messages of the desired > language. Maintaining is easy as you have the same program code for > all projects and a specific language file. Just compile each project > to a unique binary ( example: TreeBrowserEN, TreeBrowserDE ) and there > you go. > > > HTH, > Andreas > http://www.software49g.gmxhome.de Thank you Andreas, and yes that certainly does help. Now I have a good idea of how to proceed, your explanations are very clear. Your first method does indeed sound simpler and I will most likely pursue that route, although the possibility of hot switching message tables might be something to keep in mind also, and as suspected it cannot be done with System RPL. I may contact you when I get to start implementing this. It could be some time however since I've got a few other things on the go first. I appreciate your valuable input. Jacob
From: Andreas Möller on 6 May 2010 02:15 Hello, a third possibility would be to use a linked array containing your multiple languages as supported by the operating system. This would mean that you could have a maximum of three different languages (IIRC) in a message table and in total no more than 255 (#FFh) messages in one table. (Hot switching might be possible.) For switching you languages you could then use the built-in commands - >LANGUAGE. But I would not encourage you for this solution, again I would strongly advise method one as this is easiest to program and more important, easiest to maintain. Regards, Andreas http://www.software49g.gmxhome.de
From: Jacob Wall on 6 May 2010 21:41 On 05/05/2010 11:15 PM, Andreas M�ller wrote: > Hello, > > a third possibility would be to use a linked array containing your > multiple languages as supported by the operating system. > This would mean that you could have a maximum of three different > languages (IIRC) in a message table and in total no more than 255 > (#FFh) messages in one table. (Hot switching might be possible.) For > switching you languages you could then use the built-in commands - >> LANGUAGE. > > But I would not encourage you for this solution, again I would > strongly advise method one as this is easiest to program and more > important, easiest to maintain. > > Regards, > Andreas > http://www.software49g.gmxhome.de I had thought of somehow using the built in LANGUAGE setting but felt that would be tricky to pull off. The 255 maximum thing is a concern before I even get going so I experimented a little and realized that I could use tricks like this for menus for example: xNAME msg1 :: #xxx01 JstGETTHEMSG DOSTR> ; NULLNAME Messages ARRY [ "{ \22ONE\22 \22TWO\22 \22THREE\22 }" ] To think that each menu key label should take up a valuable 1/255 was troublesome, haha. Mind you not all labels would require translation. Jacob
|
Pages: 1 Prev: REVLIST Command HP 48G Next: RPN/RPL Calculator implementations, list of, regular post [long,FAQ] |