<?xml version="1.0"?>
<rss version="2.0">
	<channel>
		<title>[A5] Writing Unicode to a file</title>
		<link>http://www.allegro.cc/forums/view/613905</link>
		<description>Allegro.cc Forum Thread</description>
		<webMaster>matthew@allegro.cc (Matthew Leverton)</webMaster>
		<lastBuildDate>Thu, 13 Feb 2014 12:48:51 +0000</lastBuildDate>
	</channel>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>I have been working on a high score screen for my game (written in C using Allegro 5.1.7 and MinGW 4.7.0 with Code::Blocks 12.11 on Windows 7 64bit).  It does the usual, displays high scores etc.  If you make it on the high score screen it will prompt you to enter your name.  Now I have been busily converting my old Allegro 4 code over to Allegro 5 Unicode and after much reading on these forums and documentation I have it working, only I had the game crash completely when it went to display unicode text with the following line...</p><div class="source-code snippet"><div class="inner"><pre>      <a href="http://www.allegro.cc/manual/al_draw_ustr"><span class="a">al_draw_ustr</span></a><span class="k2">(</span>font_verdana, fontcolor,
                   WIDTH<span class="k3">/</span><span class="n">2</span>, y, ALLEGRO_ALIGN_CENTRE,
                   hiscore<span class="k2">[</span>difficulty<span class="k2">]</span><span class="k2">[</span>i<span class="k2">]</span>.name<span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>

This works fine with <span class="source-code"><a href="http://www.allegro.cc/manual/al_draw_text"><span class="a">al_draw_text</span></a><span class="k2">(</span><span class="k2">)</span></span> instead and using a C string obviously.</p><p>Now I managed to track it down to loading/saving the high score data.  When the game first starts, if there are no high scores, it writes new files with default values and it works fine, the line above displays fine as well.  But once you get a new high score and it writes new values to the disk, it doesn&#39;t seem to either write or read them back properly.</p><p>I have the following struct:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">typedef</span> <span class="k1">struct</span> HISCORES <span class="k2">{</span>
   <a href="http://www.allegro.cc/manual/ALLEGRO_USTR"><span class="a">ALLEGRO_USTR</span></a> <span class="k3">*</span>name<span class="k2">;</span>
   <span class="k1">unsigned</span> <span class="k1">long</span>  score<span class="k2">;</span>
   <span class="k1">int</span>            level<span class="k2">;</span>
   <span class="k1">char</span>           <a href="http://www.delorie.com/djgpp/doc/libc/libc_821.html" target="_blank">time</a><span class="k2">[</span>TIME_LEN<span class="k2">]</span><span class="k2">;</span>
<span class="k2">}</span> HISCORES<span class="k2">;</span>
</pre></div></div><p>

this is written with...</p><div class="source-code snippet"><div class="inner"><pre>      hiscore_file<span class="k2">[</span>i<span class="k2">]</span> <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_fopen"><span class="a">al_fopen</span></a><span class="k2">(</span>filename, <span class="s">"wb"</span><span class="k2">)</span><span class="k2">;</span>
      <span class="k1">if</span><span class="k2">(</span>hiscore_file<span class="k2">[</span>i<span class="k2">]</span><span class="k2">)</span> <span class="k2">{</span>
         <a href="http://www.allegro.cc/manual/al_fwrite"><span class="a">al_fwrite</span></a><span class="k2">(</span>hiscore_file<span class="k2">[</span>i<span class="k2">]</span>, hiscore<span class="k2">[</span>i<span class="k2">]</span>, NUM_SCORES <span class="k3">*</span> <span class="k1">sizeof</span><span class="k2">(</span>HISCORES<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
         <a href="http://www.allegro.cc/manual/al_fclose"><span class="a">al_fclose</span></a><span class="k2">(</span>hiscore_file<span class="k2">[</span>i<span class="k2">]</span><span class="k2">)</span><span class="k2">;</span>
      <span class="k2">}</span>
</pre></div></div><p>

This probably isn&#39;t the best way to do things, I normally write each struct element separately, but this was code I already had laying around from my Allegro 4 days and it has always worked, and it works when the <span class="source-code">name</span> is stored as a character array (C string) but not like this it seems?   I have similar code for reading it in.</p><p>I am wondering, will reading and writing this as a C string, converting before writing with <span class="source-code"><a href="http://www.allegro.cc/manual/al_cstr"><span class="a">al_cstr</span></a><span class="k2">(</span><span class="k2">)</span></span> solve this problem or do you think there is something else wrong?  Like I said, aside from the problems with it reading/writing, I have the Unicode name input working great (thanks to multiple posts in the forums).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Neil Roy)</author>
		<pubDate>Thu, 13 Feb 2014 02:42:47 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>The only way this could have worked before was if you had your names in a fixed size array (like <span class="source-code"><span class="k1">char</span> name<span class="k2">[</span>NAME_LEN<span class="k2">]</span></span>). What you&#39;re doing right now is writing the pointer value to file, which naturally won&#39;t work.</p><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/613905/996317#target">NiteHackr</a> said:</div><div class="quote"><p> I am wondering, will reading and writing this as a C string, converting before writing with al_cstr() solve this problem or do you think there is something else wrong?</p></div></div><p>Yes, this will work (not with <span class="source-code"><a href="http://www.allegro.cc/manual/al_cstr"><span class="a">al_cstr</span></a><span class="k2">(</span><span class="k2">)</span></span> by itself though, if you read its documentation). It&#39;s better (but more memory hungry) to do:
</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> l <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_ustr_size"><span class="a">al_ustr_size</span></a><span class="k2">(</span>name<span class="k2">)</span><span class="k2">;</span>
al_fwrite32l1<span class="k2">(</span>f, l<span class="k2">)</span><span class="k2">;</span>
<a href="http://www.allegro.cc/manual/al_fwrite"><span class="a">al_fwrite</span></a><span class="k2">(</span>l, <a href="http://www.allegro.cc/manual/al_cstr"><span class="a">al_cstr</span></a><span class="k2">(</span>name<span class="k2">)</span>, l<span class="k2">)</span><span class="k2">;</span>
</pre></div></div><p>

There isn&#39;t really a clean way to read it back, unfortunately, at least not without allocating the string twice.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Thu, 13 Feb 2014 04:12:14 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Thanks, I almost hit myself in the head when I read your response about it being a pointer!  DUH!  Why that didn&#39;t occur to me I don&#39;t know.  But you&#39;re right, I had a fixed size before just as you assumed.</p><p>Looks like you have a couple typos in here as well. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" />
</p><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/613905/996319#target">SiegeLord</a> said:</div><div class="quote"><p>
int l = al_ustr_size(name);<br />al_fwrite32l1(f, l);<br />al_fwrite(l, al_cstr(name), l);
</p></div></div><p>
Not sure what <span class="source-code">al_fwrite32l1<span class="k2">(</span>f, l<span class="k2">)</span><span class="k2">;</span></span> is, and where are you writing the name to in the last line?! <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" /></p><p>Now that I have unicode working and using truetype fonts, the width varies on the names that are entered so the number of characters allowed for your name depends on the horizontal pixels your name takes up.  I check the width of your name as it is entered in pixels now and only allow up to a certain number of pixels, which works beautifully.  I had a fixed width before based on the number of characters.  Anyhow, thanks a bunch.</p><p>I plan to read it back in as a C string and then assign that to the ustr with something like <span class="source-code"><a href="http://www.allegro.cc/manual/al_ustr_assign_cstr"><span class="a">al_ustr_assign_cstr</span></a><span class="k2">(</span>hiscore<span class="k2">[</span>dif<span class="k2">]</span><span class="k2">[</span>i<span class="k2">]</span>.name, cstrname<span class="k2">)</span><span class="k2">;</span></span></p><p>EDIT: I just noticed <span class="source-code"><a href="http://www.allegro.cc/manual/al_fget_ustr"><span class="a">al_fget_ustr</span></a><span class="k2">(</span><span class="k2">)</span></span> hmmm.... but no <span class="source-code">al_fput_ustr<span class="k2">(</span><span class="k2">)</span></span>, so I assume I still have to write it to file as a C string, but then I could read it with this?  &lt;confused&gt;</p><p>Thanks a lot for your help with this anyhow.  I guess I could have done it without asking a question in here, but I wanted to confirm I was doing it right as I am new to these unicode routines and it doesn&#39;t hurt for others to read this if they have the same questions. <img src="http://www.allegro.cc/forums/smileys/wink.gif" alt=";)" /></p><p>And just for completeness, anyone who may be curious, I display the name as it is being entered with a vertical black line at the end of  the text, like you see when typing in a message in there forums.  And as each character is typed, I get the total width of the name in pixels and test it against a defined width limit and remove the last character if it exceeds it, which works out really nice.  Just posting part of my code for anyone that may be interested anyhow...</p><div class="source-code"><div class="toolbar"><span class="button numbers"><b>#</b></span><span class="button select">Select</span><span class="button expand">Expand</span></div><div class="inner"><span class="number">  1</span><span class="c">// yourname is an ALLEGRO_USTR defined and initialized earlier</span>
<span class="number">  2</span><span class="c">// hiscore[difficulty][myscore].name is an ALLEGRO_USTR</span>
<span class="number">  3</span><span class="k1">bool</span> done <span class="k3">=</span> <span class="k1">false</span><span class="k2">;</span>
<span class="number">  4</span><span class="k1">int</span> <a href="http://www.allegro.cc/manual/key"><span class="a">key</span></a><span class="k2">;</span>
<span class="number">  5</span><span class="k1">int</span> pos <span class="k3">=</span> <span class="k2">(</span><span class="k1">int</span><span class="k2">)</span><a href="http://www.allegro.cc/manual/al_ustr_size"><span class="a">al_ustr_size</span></a><span class="k2">(</span>yourname<span class="k2">)</span><span class="k2">;</span>
<span class="number">  6</span><span class="k1">int</span> x<span class="k2">;</span>
<span class="number">  7</span>
<span class="number">  8</span><span class="k1">while</span><span class="k2">(</span><span class="k3">!</span>done<span class="k2">)</span> <span class="k2">{</span>
<span class="number">  9</span>   <span class="c">// copies a name, if one already exists to be displayed for editing</span>
<span class="number"> 10</span>   <span class="k1">if</span><span class="k2">(</span>pos&gt;0<span class="k2">)</span> <a href="http://www.allegro.cc/manual/al_ustr_assign"><span class="a">al_ustr_assign</span></a><span class="k2">(</span>hiscore<span class="k2">[</span>difficulty<span class="k2">]</span><span class="k2">[</span>myscore<span class="k2">]</span>.name, yourname<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 11</span>
<span class="number"> 12</span>   <a href="http://www.allegro.cc/manual/al_wait_for_event"><span class="a">al_wait_for_event</span></a><span class="k2">(</span>event_queue, <span class="k3">&amp;</span>event<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 13</span>   <span class="k1">switch</span><span class="k2">(</span>event.type<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 14</span>      <span class="k1">case</span> ALLEGRO_EVENT_DISPLAY_CLOSE:
<span class="number"> 15</span>         done <span class="k3">=</span> <span class="k1">true</span><span class="k2">;</span>
<span class="number"> 16</span>         <span class="k1">break</span><span class="k2">;</span>
<span class="number"> 17</span>      <span class="k1">case</span> ALLEGRO_EVENT_KEY_CHAR:
<span class="number"> 18</span>         <span class="k1">if</span><span class="k2">(</span>event.keyboard.unichar <span class="k3">&gt;</span><span class="k3">=</span> <span class="n">32</span><span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 19</span>            pos <span class="k3">+</span><span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_ustr_append_chr"><span class="a">al_ustr_append_chr</span></a><span class="k2">(</span>yourname, event.keyboard.unichar<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 20</span>            <span class="c">// Get the width of the name in pixels (because TTF varies in width)</span>
<span class="number"> 21</span>            x <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_get_text_width"><span class="a">al_get_text_width</span></a><span class="k2">(</span>font_verdana, <a href="http://www.allegro.cc/manual/al_cstr"><span class="a">al_cstr</span></a><span class="k2">(</span>yourname<span class="k2">)</span><span class="k2">)</span><span class="k2">;</span>
<span class="number"> 22</span>            <span class="k1">if</span><span class="k2">(</span>x <span class="k3">&gt;</span> MAX_NAME_LEN<span class="k2">)</span> <span class="k2">{</span>  <span class="c">// Check if the width in pixels is greater than the allowed size</span>
<span class="number"> 23</span>               <span class="k1">if</span><span class="k2">(</span><a href="http://www.allegro.cc/manual/al_ustr_prev"><span class="a">al_ustr_prev</span></a><span class="k2">(</span>yourname, <span class="k3">&amp;</span>pos<span class="k2">)</span><span class="k2">)</span> <a href="http://www.allegro.cc/manual/al_ustr_truncate"><span class="a">al_ustr_truncate</span></a><span class="k2">(</span>yourname, pos<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 24</span>            <span class="k2">}</span>
<span class="number"> 25</span>         <span class="k2">}</span>
<span class="number"> 26</span>         <span class="k1">else</span> <span class="k1">if</span><span class="k2">(</span>event.keyboard.keycode <span class="k3">=</span><span class="k3">=</span> ALLEGRO_KEY_BACKSPACE<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 27</span>            <span class="k1">if</span><span class="k2">(</span><a href="http://www.allegro.cc/manual/al_ustr_prev"><span class="a">al_ustr_prev</span></a><span class="k2">(</span>yourname, <span class="k3">&amp;</span>pos<span class="k2">)</span><span class="k2">)</span> <a href="http://www.allegro.cc/manual/al_ustr_truncate"><span class="a">al_ustr_truncate</span></a><span class="k2">(</span>yourname, pos<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 28</span>         <span class="k2">}</span>
<span class="number"> 29</span>         <span class="k1">else</span> <span class="k1">if</span><span class="k2">(</span>event.keyboard.keycode <span class="k3">=</span><span class="k3">=</span> ALLEGRO_KEY_ENTER<span class="k3">|</span><span class="k3">|</span>
<span class="number"> 30</span>                 event.keyboard.keycode <span class="k3">=</span><span class="k3">=</span> ALLEGRO_KEY_PAD_ENTER<span class="k2">)</span> <span class="k2">{</span>
<span class="number"> 31</span>            <a href="http://www.allegro.cc/manual/al_ustr_assign"><span class="a">al_ustr_assign</span></a><span class="k2">(</span>hiscore<span class="k2">[</span>difficulty<span class="k2">]</span><span class="k2">[</span>myscore<span class="k2">]</span>.name, yourname<span class="k2">)</span><span class="k2">;</span>
<span class="number"> 32</span>            done <span class="k3">=</span> <span class="k1">true</span><span class="k2">;</span>
<span class="number"> 33</span>         <span class="k2">}</span>
<span class="number"> 34</span>         <span class="k1">break</span><span class="k2">;</span>
<span class="number"> 35</span>   <span class="k2">}</span>
<span class="number"> 36</span><span class="k2">}</span>
</div></div><p>
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Neil Roy)</author>
		<pubDate>Thu, 13 Feb 2014 06:39:41 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yeah, too many l&#39;s. Here&#39;s what I meant:</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> sz <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_ustr_size"><span class="a">al_ustr_size</span></a><span class="k2">(</span>name<span class="k2">)</span><span class="k2">;</span>        <span class="c">// get the number of bytes in the name string</span>
<a href="http://www.allegro.cc/manual/al_fwrite32le"><span class="a">al_fwrite32le</span></a><span class="k2">(</span>file, sz<span class="k2">)</span><span class="k2">;</span>            <span class="c">// write the size to the file</span>
<a href="http://www.allegro.cc/manual/al_fwrite"><span class="a">al_fwrite</span></a><span class="k2">(</span>file, <a href="http://www.allegro.cc/manual/al_cstr"><span class="a">al_cstr</span></a><span class="k2">(</span>name<span class="k2">)</span>, sz<span class="k2">)</span><span class="k2">;</span> <span class="c">// write the string to the file</span>
</pre></div></div><p>

I imagine you&#39;d read the above using something like this:</p><div class="source-code snippet"><div class="inner"><pre><span class="k1">int</span> sz <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_fread32le"><span class="a">al_fread32le</span></a><span class="k2">(</span>file<span class="k2">)</span><span class="k2">;</span>             <span class="c">// read the number of bytes in the name</span>
<span class="k1">char</span><span class="k3">*</span> buf <span class="k3">=</span> <a href="http://www.delorie.com/djgpp/doc/libc/libc_551.html" target="_blank">malloc</a><span class="k2">(</span>sz<span class="k2">)</span><span class="k2">;</span>                  <span class="c">// allocate a temporary buffer for the name</span>
<a href="http://www.allegro.cc/manual/al_fread"><span class="a">al_fread</span></a><span class="k2">(</span>file, buf, sz<span class="k2">)</span><span class="k2">;</span>                 <span class="c">// read the name into the buffer</span>
name <span class="k3">=</span> <a href="http://www.allegro.cc/manual/al_ustr_new_from_buffer"><span class="a">al_ustr_new_from_buffer</span></a><span class="k2">(</span>buf, sz<span class="k2">)</span><span class="k2">;</span> <span class="c">// copy the buffer into the ustr</span>
<a href="http://www.delorie.com/djgpp/doc/libc/libc_350.html" target="_blank">free</a><span class="k2">(</span>buf<span class="k2">)</span><span class="k2">;</span>                               <span class="c">// free the temporary buffer</span>
</pre></div></div><p>

I don&#39;t think there&#39;s a way to avoid the temporary buffer, which is a bit of a bummer from an api standpoint (what is missing is a function that takes ownership of the passed data pointer).
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (SiegeLord)</author>
		<pubDate>Thu, 13 Feb 2014 09:03:53 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><p>Yay!  Thanks for that!  Wow, your timing couldn&#39;t have been better.  I had been sitting here trying different ideas out and I had wrote the size of the string first then the string and it all seemed to be writing okay but wasn&#39;t reading them all back in properly.  I tried what you suggested and it now reads and writes flawlessly, thanks a lot.</p><p>I think my problem was I wasn&#39;t writing the size properly and wasn&#39;t of course reading in back in properly as well as other stupid mistakes.</p><p>I am SO happy to finally get done this part of my game.  Graphics all work fine, sound etc... never much of a problem with those, but this was a headache.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Neil Roy)</author>
		<pubDate>Thu, 13 Feb 2014 10:00:55 +0000</pubDate>
	</item>
	<item>
		<description><![CDATA[<div class="mockup v2"><div class="quote_container"><div class="title"><a href="http://www.allegro.cc/forums/thread/613905/996328#target">SiegeLord</a> said:</div><div class="quote"><p>what is missing is a function that takes ownership of the passed data pointer</p></div></div><p>

That kind of API makes me uneasy. For one, the buffer would have to be allocated with al_malloc, or else you would need to provide the corresponding free function to be called by al_ustr_free (adding a field to ALLEGRO_USTR).</p><p>An alternative would be to allow you to reserve space in the ALLEGRO_USTR, then you could read directly into it.</p><p>But for a high score list you might as well just read into a stack-allocated buffer of reasonable size (check!), then create the ALLEGRO_USTR from that.
</p></div>]]>
		</description>
		<author>no-reply@allegro.cc (Peter Wang)</author>
		<pubDate>Thu, 13 Feb 2014 12:48:51 +0000</pubDate>
	</item>
</rss>
