Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| d5dc5c0ddf | |||
| 172ed08d40 | |||
| f27fade744 | 
@ -28,4 +28,4 @@ test:
 | 
			
		||||
  dependencies:
 | 
			
		||||
    - build_meson
 | 
			
		||||
  script:
 | 
			
		||||
    - ninja -C _build test
 | 
			
		||||
    - xvfb-run -s -noreset ninja -C _build test
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,57 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<geometry version="0.90">
 | 
			
		||||
  <bounds x="10" y="10" width="410.0000" height="229"/>
 | 
			
		||||
 | 
			
		||||
  <outline id="default" corner-radius="1.000000">
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AD01" oref="outline2" />
 | 
			
		||||
      <key name="AD02" oref="outline2" />
 | 
			
		||||
      <key name="AD03" oref="outline2" />
 | 
			
		||||
      <key name="AD04" oref="outline2" />
 | 
			
		||||
      <key name="AD05" oref="outline2" />
 | 
			
		||||
      <key name="AD06" oref="outline2" />
 | 
			
		||||
      <key name="AD07" oref="outline2" />
 | 
			
		||||
      <key name="AD08" oref="outline2" />
 | 
			
		||||
      <key name="AD09" oref="outline2" />
 | 
			
		||||
      <key name="AD10" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AC01" oref="outline2" />
 | 
			
		||||
      <key name="AC02" oref="outline2" />
 | 
			
		||||
      <key name="AC03" oref="outline2" />
 | 
			
		||||
      <key name="AC04" oref="outline2" />
 | 
			
		||||
      <key name="AC05" oref="outline2" />
 | 
			
		||||
      <key name="AC06" oref="outline2" />
 | 
			
		||||
      <key name="AC07" oref="outline2" />
 | 
			
		||||
      <key name="AC08" oref="outline2" />
 | 
			
		||||
      <key name="AC09" oref="outline2" />
 | 
			
		||||
      <key name="AC10" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="LFSH" oref="altline" />
 | 
			
		||||
      <key name="AB01" oref="outline2" />
 | 
			
		||||
      <key name="AB02" oref="outline2" />
 | 
			
		||||
      <key name="AB03" oref="outline2" />
 | 
			
		||||
      <key name="AB04" oref="outline2" />
 | 
			
		||||
      <key name="AB05" oref="outline2" />
 | 
			
		||||
      <key name="AB06" oref="outline2" />
 | 
			
		||||
      <key name="AB07" oref="outline2" />
 | 
			
		||||
      <key name="BKSP" oref="altline" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key keycode="0" name="ABC123" oref="altline" />
 | 
			
		||||
      <key name="I149" oref="altline" />
 | 
			
		||||
      <key name="SPCE" oref="spaceline" />
 | 
			
		||||
      <key name="AB08" oref="outline2" />
 | 
			
		||||
      <key name="RTRN" oref="outline7" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <outline id="outline2" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="52"/>
 | 
			
		||||
@ -14,51 +63,58 @@
 | 
			
		||||
    <point x="48.39024" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline4" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline5" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline6" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="68.68292" y="0.000000"/>
 | 
			
		||||
    <point x="68.68292" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline7" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline8" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline9" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="109.2682" y="0.000000"/>
 | 
			
		||||
    <point x="109.2682" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline10" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline13" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="79.60975" y="0.000000"/>
 | 
			
		||||
    <point x="79.60975" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="spaceline" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="150.5853" y="0.000000"/>
 | 
			
		||||
    <point x="150.5853" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
 | 
			
		||||
  <button name="Shift_L" oref="altline" />
 | 
			
		||||
  <button name="BackSpace" oref="altline" />
 | 
			
		||||
  <button name="preferences" oref="altline" />
 | 
			
		||||
  <button name="show_numbers" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="show_letters" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="show_symbols" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="period" oref="altline" />
 | 
			
		||||
  <button name="space" oref="spaceline" />
 | 
			
		||||
  <button name="Return" oref="outline7" />
 | 
			
		||||
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">q w e r t y u i o p</section>
 | 
			
		||||
    <section angle="0">a s d f g h j k l</section>
 | 
			
		||||
    <section angle="0"> Shift_L   z x c v b n m  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_numbers preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">Q W E R T Y U I O P</section>
 | 
			
		||||
    <section angle="0">A S D F G H J K L</section>
 | 
			
		||||
    <section angle="0"> Shift_L   Z X C V B N M  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_numbers preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">1 2 3 4 5 6 7 8 9 0</section>
 | 
			
		||||
    <section angle="0">at numbersign dollar percent ampersand minus underscore plus parenleft parenright</section>
 | 
			
		||||
    <section angle="0"> show_symbols   comma quotedbl quoteright colon semicolon exclam question  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_letters preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph</section>
 | 
			
		||||
    <section angle="0">copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright</section>
 | 
			
		||||
    <section angle="0"> show_numbers   backslash slash less greater equal bracketleft bracketright  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_letters preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
</geometry>
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,58 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<geometry version="0.90">
 | 
			
		||||
  <bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
 | 
			
		||||
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AD01" oref="outline2" />
 | 
			
		||||
      <key name="AD02" oref="outline2" />
 | 
			
		||||
      <key name="AD03" oref="outline2" />
 | 
			
		||||
      <key name="AD04" oref="outline2" />
 | 
			
		||||
      <key name="AD05" oref="outline2" />
 | 
			
		||||
      <key name="AD06" oref="outline2" />
 | 
			
		||||
      <key name="AD07" oref="outline2" />
 | 
			
		||||
      <key name="AD08" oref="outline2" />
 | 
			
		||||
      <key name="AD09" oref="outline2" />
 | 
			
		||||
      <key name="AD10" oref="outline2" />
 | 
			
		||||
      <key name="AD11" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AC01" oref="outline2" />
 | 
			
		||||
      <key name="AC02" oref="outline2" />
 | 
			
		||||
      <key name="AC03" oref="outline2" />
 | 
			
		||||
      <key name="AC04" oref="outline2" />
 | 
			
		||||
      <key name="AC05" oref="outline2" />
 | 
			
		||||
      <key name="AC06" oref="outline2" />
 | 
			
		||||
      <key name="AC07" oref="outline2" />
 | 
			
		||||
      <key name="AC08" oref="outline2" />
 | 
			
		||||
      <key name="AC09" oref="outline2" />
 | 
			
		||||
      <key name="AC10" oref="outline2" />
 | 
			
		||||
      <key name="AC11" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="LFSH" oref="altline" />
 | 
			
		||||
      <key name="AB01" oref="outline2" />
 | 
			
		||||
      <key name="AB02" oref="outline2" />
 | 
			
		||||
      <key name="AB03" oref="outline2" />
 | 
			
		||||
      <key name="AB04" oref="outline2" />
 | 
			
		||||
      <key name="AB05" oref="outline2" />
 | 
			
		||||
      <key name="AB06" oref="outline2" />
 | 
			
		||||
      <key name="AB07" oref="outline2" />
 | 
			
		||||
      <key name="BKSP" oref="altline" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key keycode="0" name="ABC123" oref="altline" />
 | 
			
		||||
      <key name="I149" oref="altline" />
 | 
			
		||||
      <key name="SPCE" oref="spaceline" />
 | 
			
		||||
      <key name="AB08" oref="outline2" />
 | 
			
		||||
      <key name="RTRN" oref="outline7" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <outline id="outline2" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="32" y="0.000000"/>
 | 
			
		||||
@ -68,38 +119,4 @@
 | 
			
		||||
    <point x="150.5853" y="52"/>
 | 
			
		||||
    <point x="0.000000" y="52"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
 | 
			
		||||
  <button name="Shift_L" oref="altline" />
 | 
			
		||||
  <button name="BackSpace" oref="altline" />
 | 
			
		||||
  <button name="preferences" oref="altline" />
 | 
			
		||||
  <button name="show_numbers" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="show_letters" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="show_symbols" oref="altline" keycode="0" />
 | 
			
		||||
  <button name="space" oref="spaceline" />
 | 
			
		||||
  <button name="return" oref="outline7" />
 | 
			
		||||
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">q w e r t y u i o p aring</section>
 | 
			
		||||
    <section angle="0">a s d f g h j k l oslash ae</section>
 | 
			
		||||
    <section angle="0"> Shift_L   z x c v b n m  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_numbers preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">Q W E R T Y U I O P Aring</section>
 | 
			
		||||
    <section angle="0">A S D F G H J K L Oslash AE</section>
 | 
			
		||||
    <section angle="0"> Shift_L   Z X C V B N M  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_numbers preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">1 2 3 4 5 6 7 8 9 0</section>
 | 
			
		||||
    <section angle="0">at numbersign dollar percent ampersand minus underscore plus parenleft parenright</section>
 | 
			
		||||
    <section angle="0"> show_symbols   comma quotedbl quoteright colon semicolon exclam question  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_letters preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">asciitilde quoteleft bar U00B7 squareroot Greek_pi Greek_tau division multiply paragraph</section>
 | 
			
		||||
    <section angle="0">copyright U00AE U00A3 EuroSign U00A5 asciicircum degree asterisk braceleft braceright</section>
 | 
			
		||||
    <section angle="0"> show_numbers   backslash slash less greater equal bracketleft bracketright  BackSpace </section>
 | 
			
		||||
    <section angle="0"> show_letters preferences         space        period    Return    </section>
 | 
			
		||||
  </view>
 | 
			
		||||
</geometry>
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,42 @@
 | 
			
		||||
<?xml version="1.0"?>
 | 
			
		||||
<geometry version="0.90">
 | 
			
		||||
  <bounds x="0" y="10.000000" width="426.0000" height="296.5853"/>
 | 
			
		||||
 | 
			
		||||
  <outline id="default" corner-radius="1.000000">
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AD01" oref="outline2" />
 | 
			
		||||
      <key name="AD02" oref="outline2" />
 | 
			
		||||
      <key name="AD03" oref="outline2" />
 | 
			
		||||
      <key name="AD04" oref="outline2" />
 | 
			
		||||
      <key name="AD05" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AC01" oref="outline2" />
 | 
			
		||||
      <key name="AC02" oref="outline2" />
 | 
			
		||||
      <key name="AC03" oref="outline2" />
 | 
			
		||||
      <key name="AC04" oref="outline2" />
 | 
			
		||||
      <key name="AC05" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="AB01" oref="outline2" />
 | 
			
		||||
      <key name="AB02" oref="outline2" />
 | 
			
		||||
      <key name="AB03" oref="outline2" />
 | 
			
		||||
      <key name="AB04" oref="outline2" />
 | 
			
		||||
      <key name="AB05" oref="outline2" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <section angle="0">
 | 
			
		||||
    <row orientation="1">
 | 
			
		||||
      <key name="BKSP" oref="altline" />
 | 
			
		||||
      <key name="AB06" oref="outline2" />
 | 
			
		||||
      <key name="SPCE" oref="spaceline" />
 | 
			
		||||
      <key name="RTRN" oref="outline7" />
 | 
			
		||||
    </row>
 | 
			
		||||
  </section>
 | 
			
		||||
  <outline id="outline2" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="52.44877"/>
 | 
			
		||||
@ -14,27 +48,58 @@
 | 
			
		||||
    <point x="48.39024" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline4" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline5" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="0.000000"/>
 | 
			
		||||
    <point x="59.31707" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline6" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="68.68292" y="0.000000"/>
 | 
			
		||||
    <point x="68.68292" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline7" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline8" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="0.000000"/>
 | 
			
		||||
    <point x="88.97561" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline9" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="109.2682" y="0.000000"/>
 | 
			
		||||
    <point x="109.2682" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline10" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="0.000000"/>
 | 
			
		||||
    <point x="37.46341" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="outline13" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="79.60975" y="0.000000"/>
 | 
			
		||||
    <point x="79.60975" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
  <outline id="spaceline" corner-radius="1.000000">
 | 
			
		||||
    <point x="0.000000" y="0.000000"/>
 | 
			
		||||
    <point x="120.5853" y="0.000000"/>
 | 
			
		||||
    <point x="120.5853" y="52.44877"/>
 | 
			
		||||
    <point x="0.000000" y="52.44877"/>
 | 
			
		||||
  </outline>
 | 
			
		||||
 | 
			
		||||
  <button name="BackSpace" oref="altline" />
 | 
			
		||||
  <button name="space" oref="spaceline" />
 | 
			
		||||
  <button name="Return" oref="outline7" />
 | 
			
		||||
 | 
			
		||||
  <view>
 | 
			
		||||
    <section angle="0">1 2 3 parenleft parenright</section>
 | 
			
		||||
    <section angle="0">4 5 6 numbersign asterisk</section>
 | 
			
		||||
    <section angle="0">7 8 9 plus minus</section>
 | 
			
		||||
    <section angle="0">BackSpace 0 space Return</section>
 | 
			
		||||
  </view>
 | 
			
		||||
</geometry>
 | 
			
		||||
 | 
			
		||||
@ -1,132 +1,206 @@
 | 
			
		||||
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
 | 
			
		||||
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
 | 
			
		||||
<symbols version="0.90">
 | 
			
		||||
  <symbol label="*">asterisk</symbol>
 | 
			
		||||
  <symbol label="+/=">show_symbols</symbol>
 | 
			
		||||
  <symbol label="τ">Greek_tau</symbol>
 | 
			
		||||
  <symbol label="å">aring</symbol>
 | 
			
		||||
  <symbol label="ø">oslash</symbol>
 | 
			
		||||
  <symbol label="æ">ae</symbol>
 | 
			
		||||
  <symbol label="Å">Aring</symbol>
 | 
			
		||||
  <symbol label="Ø">Oslash</symbol>
 | 
			
		||||
  <symbol label="Æ">AE</symbol>
 | 
			
		||||
  <symbol label="q">q</symbol>
 | 
			
		||||
  <symbol label="Q">Q</symbol>
 | 
			
		||||
  <symbol label="1">1</symbol>
 | 
			
		||||
  <symbol label="~">asciitilde</symbol>
 | 
			
		||||
  <symbol label="w">w</symbol>
 | 
			
		||||
  <symbol label="W">W</symbol>
 | 
			
		||||
  <symbol label="2">2</symbol>
 | 
			
		||||
  <symbol label="`">quoteleft</symbol>
 | 
			
		||||
  <symbol label="e">e</symbol>
 | 
			
		||||
  <symbol label="E">E</symbol>
 | 
			
		||||
  <symbol label="3">3</symbol>
 | 
			
		||||
  <symbol label="|">bar</symbol>
 | 
			
		||||
  <symbol label="r">r</symbol>
 | 
			
		||||
  <symbol label="R">R</symbol>
 | 
			
		||||
  <symbol label="4">4</symbol>
 | 
			
		||||
  <symbol label="·">U00B7</symbol>
 | 
			
		||||
  <symbol label="t">t</symbol>
 | 
			
		||||
  <symbol label="T">T</symbol>
 | 
			
		||||
  <symbol label="5">5</symbol>
 | 
			
		||||
  <symbol label="√">squareroot</symbol>
 | 
			
		||||
  <symbol label="y">y</symbol>
 | 
			
		||||
  <symbol label="Y">Y</symbol>
 | 
			
		||||
  <symbol label="6">6</symbol>
 | 
			
		||||
  <symbol label="π">Greek_pi</symbol>
 | 
			
		||||
  <symbol label="u">u</symbol>
 | 
			
		||||
  <symbol label="U">U</symbol>
 | 
			
		||||
  <symbol label="7">7</symbol>
 | 
			
		||||
  <symbol label="÷">division</symbol>
 | 
			
		||||
  <symbol label="i">i</symbol>
 | 
			
		||||
  <symbol label="I">I</symbol>
 | 
			
		||||
  <symbol label="8">8</symbol>
 | 
			
		||||
  <symbol label="×">multiply</symbol>
 | 
			
		||||
  <symbol label="o">o</symbol>
 | 
			
		||||
  <symbol label="O">O</symbol>
 | 
			
		||||
  <symbol label="9">9</symbol>
 | 
			
		||||
  <symbol label="¶">paragraph</symbol>
 | 
			
		||||
  <symbol label="p">p</symbol>
 | 
			
		||||
  <symbol label="P">P</symbol>
 | 
			
		||||
  <symbol label="0">0</symbol>
 | 
			
		||||
  <symbol label="△">U25B3</symbol>
 | 
			
		||||
  <symbol keyval="229" label="å">aring</symbol>
 | 
			
		||||
  <symbol keyval="197" label="Å">Aring</symbol>
 | 
			
		||||
  <symbol label="a">a</symbol>
 | 
			
		||||
  <symbol label="A">A</symbol>
 | 
			
		||||
  <symbol label="@">at</symbol>
 | 
			
		||||
  <symbol label="©">copyright</symbol>
 | 
			
		||||
  <symbol label="s">s</symbol>
 | 
			
		||||
  <symbol label="S">S</symbol>
 | 
			
		||||
  <symbol label="#">numbersign</symbol>
 | 
			
		||||
  <symbol label="®">U00AE</symbol>
 | 
			
		||||
  <symbol label="d">d</symbol>
 | 
			
		||||
  <symbol label="D">D</symbol>
 | 
			
		||||
  <symbol label="$">dollar</symbol>
 | 
			
		||||
  <symbol label="£">U00A3</symbol>
 | 
			
		||||
  <symbol label="f">f</symbol>
 | 
			
		||||
  <symbol label="F">F</symbol>
 | 
			
		||||
  <symbol label="%">percent</symbol>
 | 
			
		||||
  <symbol label="€">EuroSign</symbol>
 | 
			
		||||
  <symbol label="g">g</symbol>
 | 
			
		||||
  <symbol label="G">G</symbol>
 | 
			
		||||
  <symbol label="&">ampersand</symbol>
 | 
			
		||||
  <symbol label="¥">U00A5</symbol>
 | 
			
		||||
  <symbol label="h">h</symbol>
 | 
			
		||||
  <symbol label="H">H</symbol>
 | 
			
		||||
  <symbol label="-">minus</symbol>
 | 
			
		||||
  <symbol label="^">asciicircum</symbol>
 | 
			
		||||
  <symbol label="j">j</symbol>
 | 
			
		||||
  <symbol label="J">J</symbol>
 | 
			
		||||
  <symbol label="_">underscore</symbol>
 | 
			
		||||
  <symbol label="°">degree</symbol>
 | 
			
		||||
  <symbol label="k">k</symbol>
 | 
			
		||||
  <symbol label="K">K</symbol>
 | 
			
		||||
  <symbol label="+">plus</symbol>
 | 
			
		||||
  <symbol label="=">equal</symbol>
 | 
			
		||||
  <symbol label="l">l</symbol>
 | 
			
		||||
  <symbol label="L">L</symbol>
 | 
			
		||||
  <symbol label="(">parenleft</symbol>
 | 
			
		||||
  <symbol label="{">braceleft</symbol>
 | 
			
		||||
  <symbol keyval="248" label="ø">oslash</symbol>
 | 
			
		||||
  <symbol keyval="216" label="Ø">Oslash</symbol>
 | 
			
		||||
  <symbol label=")">parenright</symbol>
 | 
			
		||||
  <symbol label="}">braceright</symbol>
 | 
			
		||||
  <symbol keyval="230" label="æ">ae</symbol>
 | 
			
		||||
  <symbol keyval="198" label="Æ">AE</symbol>
 | 
			
		||||
  <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  <symbol keyval="65505" icon="key-shift">Shift_L</symbol>
 | 
			
		||||
  <symbol label="z">z</symbol>
 | 
			
		||||
  <symbol label="Z">Z</symbol>
 | 
			
		||||
  <symbol label=",">comma</symbol>
 | 
			
		||||
  <symbol label="\">backslash</symbol>
 | 
			
		||||
  <symbol label="x">x</symbol>
 | 
			
		||||
  <symbol label="X">X</symbol>
 | 
			
		||||
  <symbol label=""">quotedbl</symbol>
 | 
			
		||||
  <symbol label="/">slash</symbol>
 | 
			
		||||
  <symbol label="c">c</symbol>
 | 
			
		||||
  <symbol label="C">C</symbol>
 | 
			
		||||
  <symbol label="'">quoteright</symbol>
 | 
			
		||||
  <symbol label="<">less</symbol>
 | 
			
		||||
  <symbol label="v">v</symbol>
 | 
			
		||||
  <symbol label="V">V</symbol>
 | 
			
		||||
  <symbol label=":">colon</symbol>
 | 
			
		||||
  <symbol label=">">greater</symbol>
 | 
			
		||||
  <symbol label="b">b</symbol>
 | 
			
		||||
  <symbol label="B">B</symbol>
 | 
			
		||||
  <symbol label=";">semicolon</symbol>
 | 
			
		||||
  <symbol label="=">equal</symbol>
 | 
			
		||||
  <symbol label="n">n</symbol>
 | 
			
		||||
  <symbol label="N">N</symbol>
 | 
			
		||||
  <symbol label="!">exclam</symbol>
 | 
			
		||||
  <symbol label="[">bracketleft</symbol>
 | 
			
		||||
  <symbol label="m">m</symbol>
 | 
			
		||||
  <symbol label="M">M</symbol>
 | 
			
		||||
  <symbol label="?">question</symbol>
 | 
			
		||||
  <symbol label="]">bracketright</symbol>
 | 
			
		||||
  <symbol label=".">period</symbol>
 | 
			
		||||
  <symbol label="123">show_numbers</symbol>
 | 
			
		||||
  <symbol label="ABC">show_letters</symbol>
 | 
			
		||||
  <symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
			
		||||
  <symbol label=" ">space</symbol>
 | 
			
		||||
  <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  <key name="AD01">
 | 
			
		||||
    <symbol label="q">q</symbol>
 | 
			
		||||
    <symbol label="Q">Q</symbol>
 | 
			
		||||
    <symbol label="1">1</symbol>
 | 
			
		||||
    <symbol label="~">asciitilde</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD02">
 | 
			
		||||
    <symbol label="w">w</symbol>
 | 
			
		||||
    <symbol label="W">W</symbol>
 | 
			
		||||
    <symbol label="2">2</symbol>
 | 
			
		||||
    <symbol label="`">quoteleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD03">
 | 
			
		||||
    <symbol label="e">e</symbol>
 | 
			
		||||
    <symbol label="E">E</symbol>
 | 
			
		||||
    <symbol label="3">3</symbol>
 | 
			
		||||
    <symbol label="|">bar</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD04">
 | 
			
		||||
    <symbol label="r">r</symbol>
 | 
			
		||||
    <symbol label="R">R</symbol>
 | 
			
		||||
    <symbol label="4">4</symbol>
 | 
			
		||||
    <symbol label="·">U00B7</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD05">
 | 
			
		||||
    <symbol label="t">t</symbol>
 | 
			
		||||
    <symbol label="T">T</symbol>
 | 
			
		||||
    <symbol label="5">5</symbol>
 | 
			
		||||
    <symbol label="√">squareroot</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD06">
 | 
			
		||||
    <symbol label="y">y</symbol>
 | 
			
		||||
    <symbol label="Y">Y</symbol>
 | 
			
		||||
    <symbol label="6">6</symbol>
 | 
			
		||||
    <symbol label="π">Greek_pi</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD07">
 | 
			
		||||
    <symbol label="u">u</symbol>
 | 
			
		||||
    <symbol label="U">U</symbol>
 | 
			
		||||
    <symbol label="7">7</symbol>
 | 
			
		||||
    <symbol label="÷">division</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD08">
 | 
			
		||||
    <symbol label="i">i</symbol>
 | 
			
		||||
    <symbol label="I">I</symbol>
 | 
			
		||||
    <symbol label="8">8</symbol>
 | 
			
		||||
    <symbol label="×">multiply</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD09">
 | 
			
		||||
    <symbol label="o">o</symbol>
 | 
			
		||||
    <symbol label="O">O</symbol>
 | 
			
		||||
    <symbol label="9">9</symbol>
 | 
			
		||||
    <symbol label="¶">paragraph</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD10">
 | 
			
		||||
    <symbol label="p">p</symbol>
 | 
			
		||||
    <symbol label="P">P</symbol>
 | 
			
		||||
    <symbol label="0">0</symbol>
 | 
			
		||||
    <symbol label="△">U25B3</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD11">
 | 
			
		||||
    <symbol keyval="229" label="å">aring</symbol>
 | 
			
		||||
    <symbol keyval="197" label="Å">Aring</symbol>
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
    <!-- Empty labels cause keys to be hidden when the level they are defined
 | 
			
		||||
         for is shown. -->
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC01">
 | 
			
		||||
    <symbol label="a">a</symbol>
 | 
			
		||||
    <symbol label="A">A</symbol>
 | 
			
		||||
    <symbol label="@">at</symbol>
 | 
			
		||||
    <symbol label="©">copyright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC02">
 | 
			
		||||
    <symbol label="s">s</symbol>
 | 
			
		||||
    <symbol label="S">S</symbol>
 | 
			
		||||
    <symbol label="#">numbersign</symbol>
 | 
			
		||||
    <symbol label="®">U00AE</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC03">
 | 
			
		||||
    <symbol label="d">d</symbol>
 | 
			
		||||
    <symbol label="D">D</symbol>
 | 
			
		||||
    <symbol label="$">dollar</symbol>
 | 
			
		||||
    <symbol label="£">U00A3</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC04">
 | 
			
		||||
    <symbol label="f">f</symbol>
 | 
			
		||||
    <symbol label="F">F</symbol>
 | 
			
		||||
    <symbol label="%">percent</symbol>
 | 
			
		||||
    <symbol label="€">EuroSign</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC05">
 | 
			
		||||
    <symbol label="g">g</symbol>
 | 
			
		||||
    <symbol label="G">G</symbol>
 | 
			
		||||
    <symbol label="&">ampersand</symbol>
 | 
			
		||||
    <symbol label="¥">U00A5</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC06">
 | 
			
		||||
    <symbol label="h">h</symbol>
 | 
			
		||||
    <symbol label="H">H</symbol>
 | 
			
		||||
    <symbol label="-">minus</symbol>
 | 
			
		||||
    <symbol label="^">asciicircum</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC07">
 | 
			
		||||
    <symbol label="j">j</symbol>
 | 
			
		||||
    <symbol label="J">J</symbol>
 | 
			
		||||
    <symbol label="_">underscore</symbol>
 | 
			
		||||
    <symbol label="°">degree</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC08">
 | 
			
		||||
    <symbol label="k">k</symbol>
 | 
			
		||||
    <symbol label="K">K</symbol>
 | 
			
		||||
    <symbol label="+">plus</symbol>
 | 
			
		||||
    <symbol label="=">equal</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC09">
 | 
			
		||||
    <symbol label="l">l</symbol>
 | 
			
		||||
    <symbol label="L">L</symbol>
 | 
			
		||||
    <symbol label="(">parenleft</symbol>
 | 
			
		||||
    <symbol label="{">braceleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC10">
 | 
			
		||||
    <symbol keyval="248" label="ø">oslash</symbol>
 | 
			
		||||
    <symbol keyval="216" label="Ø">Oslash</symbol>
 | 
			
		||||
    <symbol label=")">parenright</symbol>
 | 
			
		||||
    <symbol label="}">braceright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC11">
 | 
			
		||||
    <symbol keyval="230" label="æ">ae</symbol>
 | 
			
		||||
    <symbol keyval="198" label="Æ">AE</symbol>
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="RTRN">
 | 
			
		||||
    <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="LFSH">
 | 
			
		||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" label="=/+">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" label="123">Shift_L</keysym>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB01">
 | 
			
		||||
    <symbol label="z">z</symbol>
 | 
			
		||||
    <symbol label="Z">Z</symbol>
 | 
			
		||||
    <symbol label=",">comma</symbol>
 | 
			
		||||
    <symbol label="\">backslash</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB02">
 | 
			
		||||
    <symbol label="x">x</symbol>
 | 
			
		||||
    <symbol label="X">X</symbol>
 | 
			
		||||
    <symbol label=""">quotedbl</symbol>
 | 
			
		||||
    <symbol label="/">slash</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB03">
 | 
			
		||||
    <symbol label="c">c</symbol>
 | 
			
		||||
    <symbol label="C">C</symbol>
 | 
			
		||||
    <symbol label="'">quoteright</symbol>
 | 
			
		||||
    <symbol label="<">less</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB04">
 | 
			
		||||
    <symbol label="v">v</symbol>
 | 
			
		||||
    <symbol label="V">V</symbol>
 | 
			
		||||
    <symbol label=":">colon</symbol>
 | 
			
		||||
    <symbol label=">">greater</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB05">
 | 
			
		||||
    <symbol label="b">b</symbol>
 | 
			
		||||
    <symbol label="B">B</symbol>
 | 
			
		||||
    <symbol label=";">semicolon</symbol>
 | 
			
		||||
    <symbol label="=">equal</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB06">
 | 
			
		||||
    <symbol label="n">n</symbol>
 | 
			
		||||
    <symbol label="N">N</symbol>
 | 
			
		||||
    <symbol label="!">exclam</symbol>
 | 
			
		||||
    <symbol label="[">bracketleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB07">
 | 
			
		||||
    <symbol label="m">m</symbol>
 | 
			
		||||
    <symbol label="M">M</symbol>
 | 
			
		||||
    <symbol label="?">question</symbol>
 | 
			
		||||
    <symbol label="]">bracketright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB08">
 | 
			
		||||
    <symbol label=".">period</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="ABC123">
 | 
			
		||||
    <symbol label="123">show-numbers</symbol>
 | 
			
		||||
    <symbol label="123">show-numbers</symbol>
 | 
			
		||||
    <symbol label="ABC">show-letters</symbol>
 | 
			
		||||
    <symbol label="ABC">show-letters</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="I149">
 | 
			
		||||
    <symbol icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="SPCE">
 | 
			
		||||
    <symbol label=" ">space</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="BKSP">
 | 
			
		||||
    <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
</symbols>
 | 
			
		||||
 | 
			
		||||
@ -1,22 +1,60 @@
 | 
			
		||||
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
 | 
			
		||||
<symbols version="0.90">
 | 
			
		||||
  <symbol label="1">1</symbol>
 | 
			
		||||
  <symbol label="2">2</symbol>
 | 
			
		||||
  <symbol label="3">3</symbol>
 | 
			
		||||
  <symbol label="(">parenleft</symbol>
 | 
			
		||||
  <symbol label=")">parenright</symbol>
 | 
			
		||||
  <symbol label="4">4</symbol>
 | 
			
		||||
  <symbol label="5">5</symbol>
 | 
			
		||||
  <symbol label="6">6</symbol>
 | 
			
		||||
  <symbol label="#">numbersign</symbol>
 | 
			
		||||
  <symbol label="*">asterisk</symbol>
 | 
			
		||||
  <symbol label="7">7</symbol>
 | 
			
		||||
  <symbol label="8">8</symbol>
 | 
			
		||||
  <symbol label="9">9</symbol>
 | 
			
		||||
  <symbol label="+">plus</symbol>
 | 
			
		||||
  <symbol label="-">minus</symbol>
 | 
			
		||||
  <symbol label="0">0</symbol>
 | 
			
		||||
  <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  <symbol label=" ">space</symbol>
 | 
			
		||||
  <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  <key name="AD01">
 | 
			
		||||
    <symbol label="1">1</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD02">
 | 
			
		||||
    <symbol label="2">2</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD03">
 | 
			
		||||
    <symbol label="3">3</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD04">
 | 
			
		||||
    <symbol label="(">parenleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD05">
 | 
			
		||||
    <symbol label=")">parenright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC01">
 | 
			
		||||
    <symbol label="4">4</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC02">
 | 
			
		||||
    <symbol label="5">5</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC03">
 | 
			
		||||
    <symbol label="6">6</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC04">
 | 
			
		||||
    <symbol label="#">numbersign</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC05">
 | 
			
		||||
    <symbol label="*">asterisk</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB01">
 | 
			
		||||
    <symbol label="7">7</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB02">
 | 
			
		||||
    <symbol label="8">8</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB03">
 | 
			
		||||
    <symbol label="9">9</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB04">
 | 
			
		||||
    <symbol label="+">plus</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB05">
 | 
			
		||||
    <symbol label="-">minus</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB06">
 | 
			
		||||
    <symbol label="0">0</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="RTRN">
 | 
			
		||||
    <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="SPCE">
 | 
			
		||||
    <symbol label=" ">space</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="BKSP">
 | 
			
		||||
    <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
</symbols>
 | 
			
		||||
 | 
			
		||||
@ -1,118 +1,194 @@
 | 
			
		||||
<?xml version='1.0' encoding='ASCII' standalone='yes'?>
 | 
			
		||||
<symbols version="0.90">
 | 
			
		||||
  <symbol label="*">asterisk</symbol>
 | 
			
		||||
  <symbol label="+/=">show_symbols</symbol>
 | 
			
		||||
  <symbol label="q">q</symbol>
 | 
			
		||||
  <symbol label="Q">Q</symbol>
 | 
			
		||||
  <symbol label="1">1</symbol>
 | 
			
		||||
  <symbol label="~">asciitilde</symbol>
 | 
			
		||||
  <symbol label="w">w</symbol>
 | 
			
		||||
  <symbol label="W">W</symbol>
 | 
			
		||||
  <symbol label="2">2</symbol>
 | 
			
		||||
  <symbol label="`">quoteleft</symbol>
 | 
			
		||||
  <symbol label="e">e</symbol>
 | 
			
		||||
  <symbol label="E">E</symbol>
 | 
			
		||||
  <symbol label="3">3</symbol>
 | 
			
		||||
  <symbol label="|">bar</symbol>
 | 
			
		||||
  <symbol label="r">r</symbol>
 | 
			
		||||
  <symbol label="R">R</symbol>
 | 
			
		||||
  <symbol label="4">4</symbol>
 | 
			
		||||
  <symbol label="·">U00B7</symbol>
 | 
			
		||||
  <symbol label="t">t</symbol>
 | 
			
		||||
  <symbol label="T">T</symbol>
 | 
			
		||||
  <symbol label="5">5</symbol>
 | 
			
		||||
  <symbol label="√">squareroot</symbol>
 | 
			
		||||
  <symbol label="y">y</symbol>
 | 
			
		||||
  <symbol label="Y">Y</symbol>
 | 
			
		||||
  <symbol label="6">6</symbol>
 | 
			
		||||
  <symbol label="π">Greek_pi</symbol>
 | 
			
		||||
  <symbol label="u">u</symbol>
 | 
			
		||||
  <symbol label="U">U</symbol>
 | 
			
		||||
  <symbol label="7">7</symbol>
 | 
			
		||||
  <symbol label="÷">division</symbol>
 | 
			
		||||
  <symbol label="i">i</symbol>
 | 
			
		||||
  <symbol label="I">I</symbol>
 | 
			
		||||
  <symbol label="8">8</symbol>
 | 
			
		||||
  <symbol label="×">multiply</symbol>
 | 
			
		||||
  <symbol label="o">o</symbol>
 | 
			
		||||
  <symbol label="O">O</symbol>
 | 
			
		||||
  <symbol label="9">9</symbol>
 | 
			
		||||
  <symbol label="¶">paragraph</symbol>
 | 
			
		||||
  <symbol label="p">p</symbol>
 | 
			
		||||
  <symbol label="P">P</symbol>
 | 
			
		||||
  <symbol label="0">0</symbol>
 | 
			
		||||
  <symbol label="τ">Greek_tau</symbol>
 | 
			
		||||
  <symbol label="a">a</symbol>
 | 
			
		||||
  <symbol label="A">A</symbol>
 | 
			
		||||
  <symbol label="@">at</symbol>
 | 
			
		||||
  <symbol label="©">copyright</symbol>
 | 
			
		||||
  <symbol label="s">s</symbol>
 | 
			
		||||
  <symbol label="S">S</symbol>
 | 
			
		||||
  <symbol label="#">numbersign</symbol>
 | 
			
		||||
  <symbol label="®">U00AE</symbol>
 | 
			
		||||
  <symbol label="d">d</symbol>
 | 
			
		||||
  <symbol label="D">D</symbol>
 | 
			
		||||
  <symbol label="$">dollar</symbol>
 | 
			
		||||
  <symbol label="£">U00A3</symbol>
 | 
			
		||||
  <symbol label="f">f</symbol>
 | 
			
		||||
  <symbol label="F">F</symbol>
 | 
			
		||||
  <symbol label="%">percent</symbol>
 | 
			
		||||
  <symbol label="€">EuroSign</symbol>
 | 
			
		||||
  <symbol label="g">g</symbol>
 | 
			
		||||
  <symbol label="G">G</symbol>
 | 
			
		||||
  <symbol label="&">ampersand</symbol>
 | 
			
		||||
  <symbol label="¥">U00A5</symbol>
 | 
			
		||||
  <symbol label="h">h</symbol>
 | 
			
		||||
  <symbol label="H">H</symbol>
 | 
			
		||||
  <symbol label="-">minus</symbol>
 | 
			
		||||
  <symbol label="^">asciicircum</symbol>
 | 
			
		||||
  <symbol label="j">j</symbol>
 | 
			
		||||
  <symbol label="J">J</symbol>
 | 
			
		||||
  <symbol label="_">underscore</symbol>
 | 
			
		||||
  <symbol label="°">degree</symbol>
 | 
			
		||||
  <symbol label="k">k</symbol>
 | 
			
		||||
  <symbol label="K">K</symbol>
 | 
			
		||||
  <symbol label="+">plus</symbol>
 | 
			
		||||
  <symbol label="=">equal</symbol>
 | 
			
		||||
  <symbol label="l">l</symbol>
 | 
			
		||||
  <symbol label="L">L</symbol>
 | 
			
		||||
  <symbol label="(">parenleft</symbol>
 | 
			
		||||
  <symbol label="{">braceleft</symbol>
 | 
			
		||||
  <symbol label=")">parenright</symbol>
 | 
			
		||||
  <symbol label="}">braceright</symbol>
 | 
			
		||||
  <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  <symbol keyval="65505" icon="key-shift">Shift_L</symbol>
 | 
			
		||||
  <symbol label="z">z</symbol>
 | 
			
		||||
  <symbol label="Z">Z</symbol>
 | 
			
		||||
  <symbol label=",">comma</symbol>
 | 
			
		||||
  <symbol label="\">backslash</symbol>
 | 
			
		||||
  <symbol label="x">x</symbol>
 | 
			
		||||
  <symbol label="X">X</symbol>
 | 
			
		||||
  <symbol label=""">quotedbl</symbol>
 | 
			
		||||
  <symbol label="/">slash</symbol>
 | 
			
		||||
  <symbol label="c">c</symbol>
 | 
			
		||||
  <symbol label="C">C</symbol>
 | 
			
		||||
  <symbol label="'">quoteright</symbol>
 | 
			
		||||
  <symbol label="<">less</symbol>
 | 
			
		||||
  <symbol label="v">v</symbol>
 | 
			
		||||
  <symbol label="V">V</symbol>
 | 
			
		||||
  <symbol label=":">colon</symbol>
 | 
			
		||||
  <symbol label=">">greater</symbol>
 | 
			
		||||
  <symbol label="b">b</symbol>
 | 
			
		||||
  <symbol label="B">B</symbol>
 | 
			
		||||
  <symbol label=";">semicolon</symbol>
 | 
			
		||||
  <symbol label="n">n</symbol>
 | 
			
		||||
  <symbol label="N">N</symbol>
 | 
			
		||||
  <symbol label="!">exclam</symbol>
 | 
			
		||||
  <symbol label="[">bracketleft</symbol>
 | 
			
		||||
  <symbol label="m">m</symbol>
 | 
			
		||||
  <symbol label="M">M</symbol>
 | 
			
		||||
  <symbol label="?">question</symbol>
 | 
			
		||||
  <symbol label="]">bracketright</symbol>
 | 
			
		||||
  <symbol label=".">period</symbol>
 | 
			
		||||
  <symbol label="123">show_numbers</symbol>
 | 
			
		||||
  <symbol label="ABC">show_letters</symbol>
 | 
			
		||||
  <symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
			
		||||
  <symbol label=" ">space</symbol>
 | 
			
		||||
  <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  <key name="AD01">
 | 
			
		||||
    <symbol label="q">q</symbol>
 | 
			
		||||
    <symbol label="Q">Q</symbol>
 | 
			
		||||
    <symbol label="1">1</symbol>
 | 
			
		||||
    <symbol label="~">asciitilde</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD02">
 | 
			
		||||
    <symbol label="w">w</symbol>
 | 
			
		||||
    <symbol label="W">W</symbol>
 | 
			
		||||
    <symbol label="2">2</symbol>
 | 
			
		||||
    <symbol label="`">quoteleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD03">
 | 
			
		||||
    <symbol label="e">e</symbol>
 | 
			
		||||
    <symbol label="E">E</symbol>
 | 
			
		||||
    <symbol label="3">3</symbol>
 | 
			
		||||
    <symbol label="|">bar</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD04">
 | 
			
		||||
    <symbol label="r">r</symbol>
 | 
			
		||||
    <symbol label="R">R</symbol>
 | 
			
		||||
    <symbol label="4">4</symbol>
 | 
			
		||||
    <symbol label="·">U00B7</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD05">
 | 
			
		||||
    <symbol label="t">t</symbol>
 | 
			
		||||
    <symbol label="T">T</symbol>
 | 
			
		||||
    <symbol label="5">5</symbol>
 | 
			
		||||
    <symbol label="√">squareroot</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD06">
 | 
			
		||||
    <symbol label="y">y</symbol>
 | 
			
		||||
    <symbol label="Y">Y</symbol>
 | 
			
		||||
    <symbol label="6">6</symbol>
 | 
			
		||||
    <symbol label="π">Greek_pi</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD07">
 | 
			
		||||
    <symbol label="u">u</symbol>
 | 
			
		||||
    <symbol label="U">U</symbol>
 | 
			
		||||
    <symbol label="7">7</symbol>
 | 
			
		||||
    <symbol label="÷">division</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD08">
 | 
			
		||||
    <symbol label="i">i</symbol>
 | 
			
		||||
    <symbol label="I">I</symbol>
 | 
			
		||||
    <symbol label="8">8</symbol>
 | 
			
		||||
    <symbol label="×">multiply</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD09">
 | 
			
		||||
    <symbol label="o">o</symbol>
 | 
			
		||||
    <symbol label="O">O</symbol>
 | 
			
		||||
    <symbol label="9">9</symbol>
 | 
			
		||||
    <symbol label="¶">paragraph</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AD10">
 | 
			
		||||
    <symbol label="p">p</symbol>
 | 
			
		||||
    <symbol label="P">P</symbol>
 | 
			
		||||
    <symbol label="0">0</symbol>
 | 
			
		||||
    <symbol label="△">U25B3</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC01">
 | 
			
		||||
    <symbol label="a">a</symbol>
 | 
			
		||||
    <symbol label="A">A</symbol>
 | 
			
		||||
    <symbol label="@">at</symbol>
 | 
			
		||||
    <symbol label="©">copyright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC02">
 | 
			
		||||
    <symbol label="s">s</symbol>
 | 
			
		||||
    <symbol label="S">S</symbol>
 | 
			
		||||
    <symbol label="#">numbersign</symbol>
 | 
			
		||||
    <symbol label="®">U00AE</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC03">
 | 
			
		||||
    <symbol label="d">d</symbol>
 | 
			
		||||
    <symbol label="D">D</symbol>
 | 
			
		||||
    <symbol label="$">dollar</symbol>
 | 
			
		||||
    <symbol label="£">U00A3</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC04">
 | 
			
		||||
    <symbol label="f">f</symbol>
 | 
			
		||||
    <symbol label="F">F</symbol>
 | 
			
		||||
    <symbol label="%">percent</symbol>
 | 
			
		||||
    <symbol label="€">EuroSign</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC05">
 | 
			
		||||
    <symbol label="g">g</symbol>
 | 
			
		||||
    <symbol label="G">G</symbol>
 | 
			
		||||
    <symbol label="&">ampersand</symbol>
 | 
			
		||||
    <symbol label="¥">U00A5</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC06">
 | 
			
		||||
    <symbol label="h">h</symbol>
 | 
			
		||||
    <symbol label="H">H</symbol>
 | 
			
		||||
    <symbol label="-">minus</symbol>
 | 
			
		||||
    <symbol label="^">asciicircum</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC07">
 | 
			
		||||
    <symbol label="j">j</symbol>
 | 
			
		||||
    <symbol label="J">J</symbol>
 | 
			
		||||
    <symbol label="_">underscore</symbol>
 | 
			
		||||
    <symbol label="°">degree</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC08">
 | 
			
		||||
    <symbol label="k">k</symbol>
 | 
			
		||||
    <symbol label="K">K</symbol>
 | 
			
		||||
    <symbol label="+">plus</symbol>
 | 
			
		||||
    <symbol label="=">equal</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC09">
 | 
			
		||||
    <symbol label="l">l</symbol>
 | 
			
		||||
    <symbol label="L">L</symbol>
 | 
			
		||||
    <symbol label="(">parenleft</symbol>
 | 
			
		||||
    <symbol label="{">braceleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AC10">
 | 
			
		||||
    <!-- Empty labels cause keys to be hidden when the level they are defined
 | 
			
		||||
         for is shown. -->
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
    <symbol label=""></symbol>
 | 
			
		||||
    <symbol label=")">parenright</symbol>
 | 
			
		||||
    <symbol label="}">braceright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="RTRN">
 | 
			
		||||
    <symbol keyval="65293" icon="key-enter">Return</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="LFSH">
 | 
			
		||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" icon="key-shift">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" label="=/+">Shift_L</keysym>
 | 
			
		||||
    <keysym keyval="65505" label="123">Shift_L</keysym>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB01">
 | 
			
		||||
    <symbol label="z">z</symbol>
 | 
			
		||||
    <symbol label="Z">Z</symbol>
 | 
			
		||||
    <symbol label=",">comma</symbol>
 | 
			
		||||
    <symbol label="\">backslash</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB02">
 | 
			
		||||
    <symbol label="x">x</symbol>
 | 
			
		||||
    <symbol label="X">X</symbol>
 | 
			
		||||
    <symbol label=""">quotedbl</symbol>
 | 
			
		||||
    <symbol label="/">slash</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB03">
 | 
			
		||||
    <symbol label="c">c</symbol>
 | 
			
		||||
    <symbol label="C">C</symbol>
 | 
			
		||||
    <symbol label="'">quoteright</symbol>
 | 
			
		||||
    <symbol label="<">less</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB04">
 | 
			
		||||
    <symbol label="v">v</symbol>
 | 
			
		||||
    <symbol label="V">V</symbol>
 | 
			
		||||
    <symbol label=":">colon</symbol>
 | 
			
		||||
    <symbol label=">">greater</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB05">
 | 
			
		||||
    <symbol label="b">b</symbol>
 | 
			
		||||
    <symbol label="B">B</symbol>
 | 
			
		||||
    <symbol label=";">semicolon</symbol>
 | 
			
		||||
    <symbol label="=">equal</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB06">
 | 
			
		||||
    <symbol label="n">n</symbol>
 | 
			
		||||
    <symbol label="N">N</symbol>
 | 
			
		||||
    <symbol label="!">exclam</symbol>
 | 
			
		||||
    <symbol label="[">bracketleft</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB07">
 | 
			
		||||
    <symbol label="m">m</symbol>
 | 
			
		||||
    <symbol label="M">M</symbol>
 | 
			
		||||
    <symbol label="?">question</symbol>
 | 
			
		||||
    <symbol label="]">bracketright</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="AB08">
 | 
			
		||||
    <symbol label=".">period</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="ABC123">
 | 
			
		||||
    <symbol label="123">show-numbers</symbol>
 | 
			
		||||
    <symbol label="123">show-numbers</symbol>
 | 
			
		||||
    <symbol label="ABC">show-letters</symbol>
 | 
			
		||||
    <symbol label="ABC">show-letters</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="I149">
 | 
			
		||||
    <symbol label="☺" icon="keyboard-mode-symbolic" tooltip="Setup">preferences</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="SPCE">
 | 
			
		||||
    <symbol label=" ">space</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
  <key name="BKSP">
 | 
			
		||||
    <symbol keyval="65288" icon="edit-clear-symbolic">BackSpace</symbol>
 | 
			
		||||
  </key>
 | 
			
		||||
</symbols>
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,7 @@
 | 
			
		||||
.key {
 | 
			
		||||
    color: #deddda;
 | 
			
		||||
    background: #464448;
 | 
			
		||||
    border-style: solid;
 | 
			
		||||
    border-width: 1px;
 | 
			
		||||
    border-width: 0.5px;
 | 
			
		||||
    border-color: #5e5c64;
 | 
			
		||||
    border-radius: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
								
							@ -1,6 +1,6 @@
 | 
			
		||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
 | 
			
		||||
Upstream-Name: squeekboard
 | 
			
		||||
Source: https://source.puri.sm/Librem5/squeekboard
 | 
			
		||||
Upstream-Name: evscript
 | 
			
		||||
Source: https://source.puri.sm/david.boddie/evscript
 | 
			
		||||
 | 
			
		||||
Files: *
 | 
			
		||||
Copyright: 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										232
									
								
								eek/eek-container.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								eek/eek-container.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,232 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-container
 | 
			
		||||
 * @short_description: Base class of a keyboard container
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekContainerClass class represents a keyboard container, which
 | 
			
		||||
 * shall be used to implement #EekKeyboard and #EekSection.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-container.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    CHILD_ADDED,
 | 
			
		||||
    CHILD_REMOVED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
typedef struct _EekContainerPrivate
 | 
			
		||||
{
 | 
			
		||||
    GList *head;
 | 
			
		||||
    GList *last;
 | 
			
		||||
} EekContainerPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekContainer, eek_container, EEK_TYPE_ELEMENT)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_real_add_child (EekContainer *self,
 | 
			
		||||
                              EekElement   *child)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerPrivate *priv = eek_container_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(child));
 | 
			
		||||
    g_object_ref (child);
 | 
			
		||||
 | 
			
		||||
    if (!priv->head) {
 | 
			
		||||
        priv->head = priv->last = g_list_prepend (priv->head, child);
 | 
			
		||||
    } else {
 | 
			
		||||
        priv->last->next = g_list_prepend (priv->last->next, child);
 | 
			
		||||
        priv->last = priv->last->next;
 | 
			
		||||
    }
 | 
			
		||||
    eek_element_set_parent (child, EEK_ELEMENT(self));
 | 
			
		||||
    g_signal_emit (self, signals[CHILD_ADDED], 0, child);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_real_remove_child (EekContainer *self,
 | 
			
		||||
                                 EekElement   *child)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerPrivate *priv = eek_container_get_instance_private (self);
 | 
			
		||||
    GList *head;
 | 
			
		||||
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(child));
 | 
			
		||||
    head = g_list_find (priv->head, child);
 | 
			
		||||
    g_return_if_fail (head);
 | 
			
		||||
    g_object_unref (child);
 | 
			
		||||
    if (head == priv->last)
 | 
			
		||||
        priv->last = g_list_previous (priv->last);
 | 
			
		||||
    priv->head = g_list_remove_link (priv->head, head);
 | 
			
		||||
    eek_element_set_parent (child, NULL);
 | 
			
		||||
    g_signal_emit (self, signals[CHILD_REMOVED], 0, child);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_real_foreach_child (EekContainer *self,
 | 
			
		||||
                                  EekCallback   callback,
 | 
			
		||||
                                  gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerPrivate *priv = eek_container_get_instance_private (self);
 | 
			
		||||
    GList *head;
 | 
			
		||||
 | 
			
		||||
    for (head = priv->head; head; head = g_list_next (head))
 | 
			
		||||
        (*callback) (EEK_ELEMENT(head->data), user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EekElement *
 | 
			
		||||
eek_container_real_find (EekContainer *self,
 | 
			
		||||
                         EekCompareFunc func,
 | 
			
		||||
                         gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerPrivate *priv = eek_container_get_instance_private (self);
 | 
			
		||||
    GList *head;
 | 
			
		||||
 | 
			
		||||
    head = g_list_find_custom (priv->head, user_data, (GCompareFunc)func);
 | 
			
		||||
    if (head)
 | 
			
		||||
        return head->data;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekContainer        *self = EEK_CONTAINER (object);
 | 
			
		||||
    EekContainerPrivate *priv = eek_container_get_instance_private (self);
 | 
			
		||||
    GList *head;
 | 
			
		||||
 | 
			
		||||
    for (head = priv->head; head; head = priv->head) {
 | 
			
		||||
        g_object_unref (head->data);
 | 
			
		||||
        priv->head = g_list_next (head);
 | 
			
		||||
        g_list_free1 (head);
 | 
			
		||||
    }
 | 
			
		||||
    G_OBJECT_CLASS(eek_container_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_class_init (EekContainerClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
    klass->add_child = eek_container_real_add_child;
 | 
			
		||||
    klass->remove_child = eek_container_real_remove_child;
 | 
			
		||||
    klass->foreach_child = eek_container_real_foreach_child;
 | 
			
		||||
    klass->find = eek_container_real_find;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    klass->child_added = NULL;
 | 
			
		||||
    klass->child_removed = NULL;
 | 
			
		||||
 | 
			
		||||
    gobject_class->dispose = eek_container_dispose;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekContainer::child-added:
 | 
			
		||||
     * @container: an #EekContainer
 | 
			
		||||
     * @element: an #EekElement
 | 
			
		||||
     *
 | 
			
		||||
     * The ::child-added signal is emitted each time an element is
 | 
			
		||||
     * added to @container.
 | 
			
		||||
     */
 | 
			
		||||
    signals[CHILD_ADDED] =
 | 
			
		||||
        g_signal_new (I_("child-added"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_FIRST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekContainerClass, child_added),
 | 
			
		||||
                      NULL, NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE, 1,
 | 
			
		||||
                      EEK_TYPE_ELEMENT);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekContainer::child-removed:
 | 
			
		||||
     * @container: an #EekContainer
 | 
			
		||||
     * @element: an #EekElement
 | 
			
		||||
     *
 | 
			
		||||
     * The ::child-removed signal is emitted each time an element is
 | 
			
		||||
     * removed from @container.
 | 
			
		||||
     */
 | 
			
		||||
    signals[CHILD_REMOVED] =
 | 
			
		||||
        g_signal_new (I_("child-removed"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_FIRST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekContainerClass, child_removed),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE, 1,
 | 
			
		||||
                      EEK_TYPE_ELEMENT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_container_init (EekContainer *self)
 | 
			
		||||
{
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_container_foreach_child:
 | 
			
		||||
 * @container: an #EekContainer
 | 
			
		||||
 * @callback: (scope call): an #EekCallback
 | 
			
		||||
 * @user_data: additional data passed to @callback
 | 
			
		||||
 *
 | 
			
		||||
 * Enumerate children of @container and run @callback with each child.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_container_foreach_child (EekContainer *container,
 | 
			
		||||
                             EekCallback   callback,
 | 
			
		||||
                             gpointer      user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_CONTAINER(container));
 | 
			
		||||
    EEK_CONTAINER_GET_CLASS(container)->foreach_child (container,
 | 
			
		||||
                                                       callback,
 | 
			
		||||
                                                       user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_container_find:
 | 
			
		||||
 * @container: an #EekContainer
 | 
			
		||||
 * @func: function to be used to compare two children
 | 
			
		||||
 * @user_data: additional data passed to @func
 | 
			
		||||
 *
 | 
			
		||||
 * Find a child which matches the criteria supplied as @func, in @container.
 | 
			
		||||
 * Returns: an #EekElement or NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
EekElement *
 | 
			
		||||
eek_container_find (EekContainer  *container,
 | 
			
		||||
                    EekCompareFunc func,
 | 
			
		||||
                    gpointer       user_data)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_CONTAINER(container), NULL);
 | 
			
		||||
    return EEK_CONTAINER_GET_CLASS(container)->find (container,
 | 
			
		||||
                                                     func,
 | 
			
		||||
                                                     user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_container_add_child (EekContainer *container, EekElement *element)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_CONTAINER(container));
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
    return EEK_CONTAINER_GET_CLASS(container)->add_child (container, element);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										94
									
								
								eek/eek-container.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								eek/eek-container.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEK_CONTAINER_H
 | 
			
		||||
#define EEK_CONTAINER_H 1
 | 
			
		||||
 | 
			
		||||
#include "eek-element.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_CONTAINER (eek_container_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE (EekContainer, eek_container, EEK, CONTAINER, EekElement)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekCallback:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @user_data: user-supplied data
 | 
			
		||||
 *
 | 
			
		||||
 * The type of the callback function used for iterating over the
 | 
			
		||||
 * children of a container, see eek_container_foreach_child().
 | 
			
		||||
 */
 | 
			
		||||
typedef void (*EekCallback) (EekElement *element, gpointer user_data);
 | 
			
		||||
typedef gint (*EekCompareFunc) (EekElement *element, gpointer user_data);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekContainerClass:
 | 
			
		||||
 * @foreach_child: virtual function for iterating over the container's children
 | 
			
		||||
 * @find: virtual function for looking up a child
 | 
			
		||||
 * @child_added: class handler for #EekContainer::child-added
 | 
			
		||||
 * @child_removed: class handler for #EekContainer::child-added
 | 
			
		||||
 */
 | 
			
		||||
struct _EekContainerClass
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekElementClass parent_class;
 | 
			
		||||
 | 
			
		||||
    void        (* add_child)      (EekContainer      *self,
 | 
			
		||||
                                    EekElement        *element);
 | 
			
		||||
 | 
			
		||||
    void        (* remove_child)   (EekContainer      *self,
 | 
			
		||||
                                    EekElement        *element);
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    void        (* foreach_child)  (EekContainer      *self,
 | 
			
		||||
                                    EekCallback        callback,
 | 
			
		||||
                                    gpointer           user_data);
 | 
			
		||||
    EekElement *(* find)           (EekContainer      *self,
 | 
			
		||||
                                    EekCompareFunc     func,
 | 
			
		||||
                                    gpointer           data);
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    void        (* child_added)    (EekContainer      *self,
 | 
			
		||||
                                    EekElement        *element);
 | 
			
		||||
    void        (* child_removed)  (EekContainer      *self,
 | 
			
		||||
                                    EekElement        *element);
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* padding */
 | 
			
		||||
    gpointer pdummy[24];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType       eek_container_get_type      (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void        eek_container_foreach_child (EekContainer  *container,
 | 
			
		||||
                                         EekCallback    callback,
 | 
			
		||||
                                         gpointer       user_data);
 | 
			
		||||
EekElement *eek_container_find          (EekContainer  *container,
 | 
			
		||||
                                         EekCompareFunc func,
 | 
			
		||||
                                         gpointer       user_data);
 | 
			
		||||
void        eek_container_add_child     (EekContainer  *container,
 | 
			
		||||
                                         EekElement    *element);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_CONTAINER_H */
 | 
			
		||||
@ -31,23 +31,51 @@
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-element.h"
 | 
			
		||||
#include "eek-container.h"
 | 
			
		||||
#include "eek-marshalers.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_NAME,
 | 
			
		||||
    PROP_BOUNDS,
 | 
			
		||||
    PROP_GROUP,
 | 
			
		||||
    PROP_LEVEL,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    SYMBOL_INDEX_CHANGED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
typedef struct _EekElementPrivate
 | 
			
		||||
{
 | 
			
		||||
    gchar *name;
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
    EekElement *parent;
 | 
			
		||||
    gint group;
 | 
			
		||||
    gint level;
 | 
			
		||||
} EekElementPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (EekElement, eek_element, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_element_real_symbol_index_changed (EekElement *self,
 | 
			
		||||
                                       gint        group,
 | 
			
		||||
                                       gint        level)
 | 
			
		||||
{
 | 
			
		||||
    // g_debug ("symbol-index-changed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_element_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekElement        *self = EEK_ELEMENT (object);
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->name);
 | 
			
		||||
    G_OBJECT_CLASS (eek_element_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -60,9 +88,19 @@ eek_element_set_property (GObject      *object,
 | 
			
		||||
    EekElement *element = EEK_ELEMENT(object);
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_NAME:
 | 
			
		||||
        eek_element_set_name (element,
 | 
			
		||||
                              g_value_dup_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_BOUNDS:
 | 
			
		||||
        eek_element_set_bounds (element, g_value_get_boxed (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_GROUP:
 | 
			
		||||
        eek_element_set_group (element, g_value_get_int (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_LEVEL:
 | 
			
		||||
        eek_element_set_level (element, g_value_get_int (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
@ -79,10 +117,19 @@ eek_element_get_property (GObject    *object,
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_NAME:
 | 
			
		||||
        g_value_set_string (value, eek_element_get_name (element));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_BOUNDS:
 | 
			
		||||
        eek_element_get_bounds (element, &bounds);
 | 
			
		||||
        g_value_set_boxed (value, &bounds);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_GROUP:
 | 
			
		||||
        g_value_set_int (value, eek_element_get_group (element));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_LEVEL:
 | 
			
		||||
        g_value_set_int (value, eek_element_get_level (element));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
@ -96,10 +143,26 @@ eek_element_class_init (EekElementClass *klass)
 | 
			
		||||
    GParamSpec        *pspec;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    klass->symbol_index_changed = eek_element_real_symbol_index_changed;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_element_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_element_get_property;
 | 
			
		||||
    gobject_class->finalize     = eek_element_finalize;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekElement:name:
 | 
			
		||||
     *
 | 
			
		||||
     * The name of #EekElement.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_string ("name",
 | 
			
		||||
                                 "Name",
 | 
			
		||||
                                 "Name",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_NAME,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekElement:bounds:
 | 
			
		||||
     *
 | 
			
		||||
@ -113,12 +176,149 @@ eek_element_class_init (EekElementClass *klass)
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_BOUNDS,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekElement:group:
 | 
			
		||||
     *
 | 
			
		||||
     * The group value of the symbol index of #EekElement.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_int ("group",
 | 
			
		||||
                              "Group",
 | 
			
		||||
                              "Group value of the symbol index",
 | 
			
		||||
                              -1, G_MAXINT, -1,
 | 
			
		||||
                              G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_GROUP,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekElement:level:
 | 
			
		||||
     *
 | 
			
		||||
     * The level value of the symbol index of #EekElement.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_int ("level",
 | 
			
		||||
                              "Level",
 | 
			
		||||
                              "Level value of the symbol index",
 | 
			
		||||
                              -1, G_MAXINT, -1,
 | 
			
		||||
                              G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_LEVEL,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekElement::symbol-index-changed:
 | 
			
		||||
     * @element: an #EekElement
 | 
			
		||||
     * @group: row index of the symbol matrix of keys on @element
 | 
			
		||||
     * @level: column index of the symbol matrix of keys on @element
 | 
			
		||||
     *
 | 
			
		||||
     * The ::symbol-index-changed signal is emitted each time the
 | 
			
		||||
     * global configuration of group/level index changes.
 | 
			
		||||
     */
 | 
			
		||||
    signals[SYMBOL_INDEX_CHANGED] =
 | 
			
		||||
        g_signal_new (I_("symbol-index-changed"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekElementClass, symbol_index_changed),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      _eek_marshal_VOID__INT_INT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      2,
 | 
			
		||||
                      G_TYPE_INT,
 | 
			
		||||
                      G_TYPE_INT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_element_init (EekElement *self)
 | 
			
		||||
{
 | 
			
		||||
    (void)self;
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    priv->group = -1;
 | 
			
		||||
    priv->level = -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_parent:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @parent: (allow-none): an #EekElement or %NULL
 | 
			
		||||
 *
 | 
			
		||||
 * Set the parent of @element to @parent.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_parent (EekElement *element,
 | 
			
		||||
                        EekElement *parent)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
    g_return_if_fail (parent == NULL || EEK_IS_ELEMENT(parent));
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    if (priv->parent == parent)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (priv->parent != NULL) {
 | 
			
		||||
        /* release self-reference acquired when setting parent */
 | 
			
		||||
        g_object_unref (element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (parent != NULL) {
 | 
			
		||||
        g_object_ref (element);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    priv->parent = parent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_parent:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 *
 | 
			
		||||
 * Get the parent of @element.
 | 
			
		||||
 * Returns: an #EekElement if the parent is set
 | 
			
		||||
 */
 | 
			
		||||
EekElement *
 | 
			
		||||
eek_element_get_parent (EekElement *element)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    return priv->parent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_name:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @name: name of @element
 | 
			
		||||
 *
 | 
			
		||||
 * Set the name of @element to @name.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_name (EekElement  *element,
 | 
			
		||||
                      const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->name);
 | 
			
		||||
    priv->name = g_strdup (name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_name:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 *
 | 
			
		||||
 * Get the name of @element.
 | 
			
		||||
 * Returns: the name of @element or NULL when the name is not set
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_element_get_name (EekElement  *element)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_ELEMENT(element), NULL);
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    return priv->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -161,3 +361,211 @@ eek_element_get_bounds (EekElement  *element,
 | 
			
		||||
 | 
			
		||||
    memcpy (bounds, &priv->bounds, sizeof(EekBounds));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_absolute_position:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @x: pointer where the X coordinate of @element will be stored
 | 
			
		||||
 * @y: pointer where the Y coordinate of @element will be stored
 | 
			
		||||
 *
 | 
			
		||||
 * Compute the absolute position of @element.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_get_absolute_position (EekElement *element,
 | 
			
		||||
                                   gdouble    *x,
 | 
			
		||||
                                   gdouble    *y)
 | 
			
		||||
{
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
    gdouble ax = 0.0, ay = 0.0;
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        eek_element_get_bounds (element, &bounds);
 | 
			
		||||
        ax += bounds.x;
 | 
			
		||||
        ay += bounds.y;
 | 
			
		||||
    } while ((element = eek_element_get_parent (element)) != NULL);
 | 
			
		||||
    *x = ax;
 | 
			
		||||
    *y = ay;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_position:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @x: X coordinate of top left corner
 | 
			
		||||
 * @y: Y coordinate of top left corner
 | 
			
		||||
 *
 | 
			
		||||
 * Set the relative position of @element.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_position (EekElement *element,
 | 
			
		||||
                          gdouble     x,
 | 
			
		||||
                          gdouble     y)
 | 
			
		||||
{
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    eek_element_get_bounds (element, &bounds);
 | 
			
		||||
    bounds.x = x;
 | 
			
		||||
    bounds.y = y;
 | 
			
		||||
    eek_element_set_bounds (element, &bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_size:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @width: width of @element
 | 
			
		||||
 * @height: height of @element
 | 
			
		||||
 *
 | 
			
		||||
 * Set the size of @element.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_size (EekElement  *element,
 | 
			
		||||
                      gdouble      width,
 | 
			
		||||
                      gdouble      height)
 | 
			
		||||
{
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    eek_element_get_bounds (element, &bounds);
 | 
			
		||||
    bounds.width = width;
 | 
			
		||||
    bounds.height = height;
 | 
			
		||||
    eek_element_set_bounds (element, &bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_symbol_index:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @group: row index of the symbol matrix
 | 
			
		||||
 * @level: column index of the symbol matrix
 | 
			
		||||
 *
 | 
			
		||||
 * Set the default index of the symbol matrices of @element.  The
 | 
			
		||||
 * setting affects the child, if child does not have the index set, as
 | 
			
		||||
 * well as this element.  To unset, pass -1 as group/level.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_symbol_index (EekElement *element,
 | 
			
		||||
                              gint        group,
 | 
			
		||||
                              gint        level)
 | 
			
		||||
{
 | 
			
		||||
    gboolean emit_signal;
 | 
			
		||||
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
 | 
			
		||||
    emit_signal = group != eek_element_get_group (element) ||
 | 
			
		||||
        level != eek_element_get_level (element);
 | 
			
		||||
 | 
			
		||||
    eek_element_set_group (element, group);
 | 
			
		||||
    eek_element_set_level (element, level);
 | 
			
		||||
 | 
			
		||||
    if (emit_signal)
 | 
			
		||||
        g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0, group, level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_symbol_index:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @group: a pointer where the group value of the symbol index will be stored
 | 
			
		||||
 * @level: a pointer where the level value of the symbol index will be stored
 | 
			
		||||
 *
 | 
			
		||||
 * Get the default index of the symbol matrices of @element.
 | 
			
		||||
 * If the index is not set, -1 will be returned.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_get_symbol_index (EekElement *element,
 | 
			
		||||
                              gint       *group,
 | 
			
		||||
                              gint       *level)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
    g_return_if_fail (group != NULL || level != NULL);
 | 
			
		||||
    if (group != NULL)
 | 
			
		||||
        *group = eek_element_get_group (element);
 | 
			
		||||
    if (level != NULL)
 | 
			
		||||
        *level = eek_element_get_level (element);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_group:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @group: group index of @element
 | 
			
		||||
 *
 | 
			
		||||
 * Set the group value of the default symbol index of @element.  To
 | 
			
		||||
 * unset, pass -1 as @group.
 | 
			
		||||
 *
 | 
			
		||||
 * See also: eek_element_set_symbol_index()
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_group (EekElement *element,
 | 
			
		||||
                       gint        group)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    if (priv->group != group) {
 | 
			
		||||
        priv->group = group;
 | 
			
		||||
        g_object_notify (G_OBJECT(element), "group");
 | 
			
		||||
        g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
 | 
			
		||||
                       group, priv->level);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_set_level:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 * @level: level index of @element
 | 
			
		||||
 *
 | 
			
		||||
 * Set the level value of the default symbol index of @element.  To
 | 
			
		||||
 * unset, pass -1 as @level.
 | 
			
		||||
 *
 | 
			
		||||
 * See also: eek_element_set_symbol_index()
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_element_set_level (EekElement *element,
 | 
			
		||||
                       gint        level)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_ELEMENT(element));
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    if (priv->level != level) {
 | 
			
		||||
        priv->level = level;
 | 
			
		||||
        g_object_notify (G_OBJECT(element), "level");
 | 
			
		||||
        g_signal_emit (element, signals[SYMBOL_INDEX_CHANGED], 0,
 | 
			
		||||
                       priv->group, level);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_group:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 *
 | 
			
		||||
 * Return the group value of the default symbol index of @element.
 | 
			
		||||
 * If the value is not set, -1 will be returned.
 | 
			
		||||
 *
 | 
			
		||||
 * See also: eek_element_get_symbol_index()
 | 
			
		||||
 */
 | 
			
		||||
gint
 | 
			
		||||
eek_element_get_group (EekElement *element)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    return priv->group;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_element_get_level:
 | 
			
		||||
 * @element: an #EekElement
 | 
			
		||||
 *
 | 
			
		||||
 * Return the level value of the default symbol index of @element.
 | 
			
		||||
 * If the value is not set, -1 will be returned.
 | 
			
		||||
 *
 | 
			
		||||
 * See also: eek_element_get_symbol_index()
 | 
			
		||||
 */
 | 
			
		||||
gint
 | 
			
		||||
eek_element_get_level (EekElement *element)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_ELEMENT(element), -1);
 | 
			
		||||
 | 
			
		||||
    EekElementPrivate *priv = eek_element_get_instance_private (element);
 | 
			
		||||
 | 
			
		||||
    return priv->level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -36,10 +36,18 @@ struct _EekElementClass
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    void                  (* symbol_index_changed) (EekElement  *self,
 | 
			
		||||
                                                    gint         group,
 | 
			
		||||
                                                    gint         level);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType        eek_element_get_type              (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void         eek_element_set_parent            (EekElement  *element,
 | 
			
		||||
                                                EekElement  *parent);
 | 
			
		||||
EekElement  *eek_element_get_parent            (EekElement  *element);
 | 
			
		||||
void         eek_element_set_name              (EekElement  *element,
 | 
			
		||||
                                                const gchar *name);
 | 
			
		||||
 | 
			
		||||
@ -51,5 +59,29 @@ void         eek_element_set_bounds            (EekElement  *element,
 | 
			
		||||
void         eek_element_get_bounds            (EekElement  *element,
 | 
			
		||||
                                                EekBounds   *bounds);
 | 
			
		||||
 | 
			
		||||
void         eek_element_set_position          (EekElement  *element,
 | 
			
		||||
                                                gdouble      x,
 | 
			
		||||
                                                gdouble      y);
 | 
			
		||||
void         eek_element_set_size              (EekElement  *element,
 | 
			
		||||
                                                gdouble      width,
 | 
			
		||||
                                                gdouble      height);
 | 
			
		||||
 | 
			
		||||
void         eek_element_get_absolute_position (EekElement  *element,
 | 
			
		||||
                                                gdouble     *x,
 | 
			
		||||
                                                gdouble     *y);
 | 
			
		||||
 | 
			
		||||
void         eek_element_set_symbol_index      (EekElement  *element,
 | 
			
		||||
                                                gint         group,
 | 
			
		||||
                                                gint         level);
 | 
			
		||||
void         eek_element_get_symbol_index      (EekElement  *element,
 | 
			
		||||
                                                gint        *group,
 | 
			
		||||
                                                gint        *level);
 | 
			
		||||
void         eek_element_set_group             (EekElement  *element,
 | 
			
		||||
                                                gint         group);
 | 
			
		||||
void         eek_element_set_level             (EekElement  *element,
 | 
			
		||||
                                                gint         level);
 | 
			
		||||
gint         eek_element_get_group             (EekElement  *element);
 | 
			
		||||
gint         eek_element_get_level             (EekElement  *element);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_ELEMENT_H */
 | 
			
		||||
 | 
			
		||||
@ -32,14 +32,16 @@
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-gtk-keyboard.h"
 | 
			
		||||
#include "eek-renderer.h"
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "src/symbol.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-gtk-keyboard.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_KEYBOARD,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -52,25 +54,34 @@ enum {
 | 
			
		||||
typedef struct _EekGtkKeyboardPrivate
 | 
			
		||||
{
 | 
			
		||||
    EekRenderer *renderer;
 | 
			
		||||
    LevelKeyboard *keyboard;
 | 
			
		||||
    GtkCssProvider *css_provider;
 | 
			
		||||
    GtkStyleContext *scontext;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekTheme *theme;
 | 
			
		||||
 | 
			
		||||
    GdkEventSequence *sequence; // unowned reference
 | 
			
		||||
} EekGtkKeyboardPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (EekGtkKeyboard, eek_gtk_keyboard, GTK_TYPE_DRAWING_AREA)
 | 
			
		||||
 | 
			
		||||
static void       on_button_pressed          (struct squeek_button *button, struct squeek_view *view,
 | 
			
		||||
static void       on_key_pressed          (EekKey      *key,
 | 
			
		||||
                                           EekGtkKeyboard *self);
 | 
			
		||||
static void       on_button_released         (struct squeek_button *button,
 | 
			
		||||
                                           struct squeek_view *view,
 | 
			
		||||
static void       on_key_released         (EekKey      *key,
 | 
			
		||||
                                           EekGtkKeyboard *self);
 | 
			
		||||
static void       render_pressed_button      (GtkWidget   *widget, struct button_place *place);
 | 
			
		||||
static void       render_locked_button       (GtkWidget   *widget,
 | 
			
		||||
                                           struct button_place *place);
 | 
			
		||||
static void       render_released_button     (GtkWidget   *widget,
 | 
			
		||||
                                           struct squeek_button *button);
 | 
			
		||||
static void       on_key_locked          (EekKeyboard *keyboard,
 | 
			
		||||
                                           EekKey      *key,
 | 
			
		||||
                                           gpointer     user_data);
 | 
			
		||||
static void       on_key_unlocked         (EekKeyboard *keyboard,
 | 
			
		||||
                                           EekKey      *key,
 | 
			
		||||
                                           gpointer     user_data);
 | 
			
		||||
static void       on_symbol_index_changed (EekKeyboard *keyboard,
 | 
			
		||||
                                           gint         group,
 | 
			
		||||
                                           gint         level,
 | 
			
		||||
                                           gpointer     user_data);
 | 
			
		||||
static void       render_pressed_key      (GtkWidget   *widget,
 | 
			
		||||
                                           EekKey      *key);
 | 
			
		||||
static void       render_locked_key       (GtkWidget   *widget,
 | 
			
		||||
                                           EekKey      *key);
 | 
			
		||||
static void       render_released_key     (GtkWidget   *widget,
 | 
			
		||||
                                           EekKey      *key);
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_gtk_keyboard_real_realize (GtkWidget      *self)
 | 
			
		||||
@ -93,12 +104,17 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
			
		||||
    EekGtkKeyboardPrivate *priv =
 | 
			
		||||
	    eek_gtk_keyboard_get_instance_private (EEK_GTK_KEYBOARD (self));
 | 
			
		||||
    GtkAllocation allocation;
 | 
			
		||||
    GList *list, *head;
 | 
			
		||||
 | 
			
		||||
    gtk_widget_get_allocation (self, &allocation);
 | 
			
		||||
 | 
			
		||||
    if (!priv->renderer) {
 | 
			
		||||
        PangoContext *pcontext = gtk_widget_get_pango_context (self);
 | 
			
		||||
        PangoContext *pcontext;
 | 
			
		||||
 | 
			
		||||
        priv->renderer = eek_renderer_new (priv->keyboard, pcontext, priv->scontext);
 | 
			
		||||
        pcontext = gtk_widget_get_pango_context (self);
 | 
			
		||||
        priv->renderer = eek_renderer_new (priv->keyboard, pcontext);
 | 
			
		||||
        if (priv->theme)
 | 
			
		||||
            eek_renderer_set_theme (priv->renderer, priv->theme);
 | 
			
		||||
 | 
			
		||||
        eek_renderer_set_allocation_size (priv->renderer,
 | 
			
		||||
                                          allocation.width,
 | 
			
		||||
@ -109,29 +125,19 @@ eek_gtk_keyboard_real_draw (GtkWidget *self,
 | 
			
		||||
 | 
			
		||||
    eek_renderer_render_keyboard (priv->renderer, cr);
 | 
			
		||||
 | 
			
		||||
    struct squeek_view *view = priv->keyboard->views[priv->keyboard->level];
 | 
			
		||||
 | 
			
		||||
    /* redraw pressed key */
 | 
			
		||||
    const GList *list = priv->keyboard->pressed_buttons;
 | 
			
		||||
    for (const GList *head = list; head; head = g_list_next (head)) {
 | 
			
		||||
        struct button_place place = squeek_view_find_key(
 | 
			
		||||
            view, squeek_button_get_key(head->data)
 | 
			
		||||
        );
 | 
			
		||||
        if (place.button)
 | 
			
		||||
            render_pressed_button (self, &place);
 | 
			
		||||
    list = eek_keyboard_get_pressed_keys (priv->keyboard);
 | 
			
		||||
    for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
        render_pressed_key (self, head->data);
 | 
			
		||||
    }
 | 
			
		||||
    g_list_free (list);
 | 
			
		||||
 | 
			
		||||
    /* redraw locked key */
 | 
			
		||||
    list = priv->keyboard->locked_buttons;
 | 
			
		||||
    for (const GList *head = list; head; head = g_list_next (head)) {
 | 
			
		||||
        struct button_place place = squeek_view_find_key(
 | 
			
		||||
            view, squeek_button_get_key(
 | 
			
		||||
                ((EekModifierKey *)head->data)->button
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
        if (place.button)
 | 
			
		||||
            render_locked_button (self, &place);
 | 
			
		||||
    list = eek_keyboard_get_locked_keys (priv->keyboard);
 | 
			
		||||
    for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
        render_locked_key (self, ((EekModifierKey *)head->data)->key);
 | 
			
		||||
    }
 | 
			
		||||
    g_list_free (list);
 | 
			
		||||
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
@ -153,63 +159,51 @@ eek_gtk_keyboard_real_size_allocate (GtkWidget     *self,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void depress(EekGtkKeyboard *self,
 | 
			
		||||
                    gdouble x, gdouble y, guint32 time)
 | 
			
		||||
{
 | 
			
		||||
                    gdouble x, gdouble y, guint32 time) {
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    struct squeek_view *view = level_keyboard_current(priv->keyboard);
 | 
			
		||||
    struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
 | 
			
		||||
    EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
 | 
			
		||||
 | 
			
		||||
    if (button) {
 | 
			
		||||
        eek_keyboard_press_button(priv->keyboard, button, time);
 | 
			
		||||
        on_button_pressed(button, view, self);
 | 
			
		||||
    if (key) {
 | 
			
		||||
        eek_keyboard_press_key(priv->keyboard, key, time);
 | 
			
		||||
        on_key_pressed(key, self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void drag(EekGtkKeyboard *self,
 | 
			
		||||
                 gdouble x, gdouble y, guint32 time) {
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    struct squeek_view *view = level_keyboard_current(priv->keyboard);
 | 
			
		||||
    struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer, view, x, y);
 | 
			
		||||
    GList *list, *head;
 | 
			
		||||
    EekKey *key = eek_renderer_find_key_by_position (priv->renderer, x, y);
 | 
			
		||||
 | 
			
		||||
    list = g_list_copy(priv->keyboard->pressed_buttons);
 | 
			
		||||
 | 
			
		||||
    if (button) {
 | 
			
		||||
    if (key) {
 | 
			
		||||
        GList *list, *head;
 | 
			
		||||
        gboolean found = FALSE;
 | 
			
		||||
 | 
			
		||||
        list = eek_keyboard_get_pressed_keys (priv->keyboard);
 | 
			
		||||
        for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
            if (head->data == button) {
 | 
			
		||||
            if (head->data == key)
 | 
			
		||||
                found = TRUE;
 | 
			
		||||
            } else {
 | 
			
		||||
                eek_keyboard_release_button(priv->keyboard, head->data, time);
 | 
			
		||||
                on_button_released(button, view, self);
 | 
			
		||||
            else {
 | 
			
		||||
                eek_keyboard_release_key(priv->keyboard, EEK_KEY(head->data), time);
 | 
			
		||||
                on_key_released(key, self);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        g_list_free (list);
 | 
			
		||||
 | 
			
		||||
        if (!found) {
 | 
			
		||||
            eek_keyboard_press_button(priv->keyboard, button, time);
 | 
			
		||||
            on_button_pressed(button, view, self);
 | 
			
		||||
            eek_keyboard_press_key(priv->keyboard, key, time);
 | 
			
		||||
            on_key_pressed(key, self);
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
            eek_keyboard_release_button(priv->keyboard, head->data, time);
 | 
			
		||||
            on_button_released(head->data, view, self);
 | 
			
		||||
        }
 | 
			
		||||
        g_list_free (list);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void release(EekGtkKeyboard *self, guint32 time) {
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    struct squeek_view *view = level_keyboard_current(priv->keyboard);
 | 
			
		||||
 | 
			
		||||
    GList *list = g_list_copy(priv->keyboard->pressed_buttons);
 | 
			
		||||
    GList *list = eek_keyboard_get_pressed_keys (priv->keyboard);
 | 
			
		||||
    for (GList *head = list; head; head = g_list_next (head)) {
 | 
			
		||||
        struct squeek_button *button = head->data;
 | 
			
		||||
        eek_keyboard_release_button(priv->keyboard, button, time);
 | 
			
		||||
        on_button_released(button, view, self);
 | 
			
		||||
        EekKey *key = EEK_KEY(head->data);
 | 
			
		||||
        eek_keyboard_release_key(priv->keyboard, key, time);
 | 
			
		||||
        on_key_released(key, self);
 | 
			
		||||
    }
 | 
			
		||||
    g_list_free (list);
 | 
			
		||||
}
 | 
			
		||||
@ -292,7 +286,7 @@ eek_gtk_keyboard_real_unmap (GtkWidget *self)
 | 
			
		||||
           elements, so that the default handler of
 | 
			
		||||
           EekKeyboard::key-released signal can remove elements from its
 | 
			
		||||
           internal copy */
 | 
			
		||||
        list = g_list_copy(priv->keyboard->pressed_buttons);
 | 
			
		||||
        list = eek_keyboard_get_pressed_keys (priv->keyboard);
 | 
			
		||||
        for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
            g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey released");
 | 
			
		||||
            g_signal_emit_by_name (head->data, "released");
 | 
			
		||||
@ -312,15 +306,15 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget  *widget,
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    struct squeek_view *view = level_keyboard_current(priv->keyboard);
 | 
			
		||||
 | 
			
		||||
    struct squeek_button *button = eek_renderer_find_button_by_position (priv->renderer,
 | 
			
		||||
                                                     view,
 | 
			
		||||
                                                     (gdouble)x,
 | 
			
		||||
                                                     (gdouble)y);
 | 
			
		||||
    if (button) {
 | 
			
		||||
        //struct squeek_symbol *symbol = eek_key_get_symbol_at_index(key, 0, priv->keyboard->level);
 | 
			
		||||
        const gchar *text = NULL; // FIXME
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
 | 
			
		||||
    key = eek_renderer_find_key_by_position (priv->renderer,
 | 
			
		||||
                                             (gdouble)x,
 | 
			
		||||
                                             (gdouble)y);
 | 
			
		||||
    if (key) {
 | 
			
		||||
        EekSymbol *symbol = eek_key_get_symbol (key);
 | 
			
		||||
        const gchar *text = eek_symbol_get_tooltip (symbol);
 | 
			
		||||
        if (text) {
 | 
			
		||||
            gtk_tooltip_set_text (tooltip, text);
 | 
			
		||||
            return TRUE;
 | 
			
		||||
@ -329,13 +323,43 @@ eek_gtk_keyboard_real_query_tooltip (GtkWidget  *widget,
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_gtk_keyboard_set_keyboard (EekGtkKeyboard *self,
 | 
			
		||||
                               EekKeyboard    *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    if (priv->keyboard == keyboard)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (priv->keyboard) {
 | 
			
		||||
        g_signal_handlers_disconnect_by_data(priv->keyboard, self);
 | 
			
		||||
        g_object_unref (priv->keyboard);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    priv->keyboard = g_object_ref (keyboard);
 | 
			
		||||
 | 
			
		||||
    g_signal_connect (priv->keyboard, "key-locked",
 | 
			
		||||
                      G_CALLBACK(on_key_locked), self);
 | 
			
		||||
    g_signal_connect (priv->keyboard, "key-unlocked",
 | 
			
		||||
                      G_CALLBACK(on_key_unlocked), self);
 | 
			
		||||
    g_signal_connect (priv->keyboard, "symbol-index-changed",
 | 
			
		||||
                      G_CALLBACK(on_symbol_index_changed), self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_gtk_keyboard_set_property (GObject      *object,
 | 
			
		||||
                               guint         prop_id,
 | 
			
		||||
                               const GValue *value,
 | 
			
		||||
                               GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_KEYBOARD:
 | 
			
		||||
        keyboard = g_value_get_object (value);
 | 
			
		||||
        eek_gtk_keyboard_set_keyboard (EEK_GTK_KEYBOARD(object), keyboard);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
@ -356,16 +380,23 @@ eek_gtk_keyboard_dispose (GObject *object)
 | 
			
		||||
    if (priv->keyboard) {
 | 
			
		||||
        GList *list, *head;
 | 
			
		||||
 | 
			
		||||
        list = g_list_copy(priv->keyboard->pressed_buttons);
 | 
			
		||||
        g_signal_handlers_disconnect_by_data(priv->keyboard, self);
 | 
			
		||||
        list = eek_keyboard_get_pressed_keys (priv->keyboard);
 | 
			
		||||
        for (head = list; head; head = g_list_next (head)) {
 | 
			
		||||
            g_log("squeek", G_LOG_LEVEL_DEBUG, "emit EekKey pressed");
 | 
			
		||||
            g_signal_emit_by_name (head->data, "released", level_keyboard_current(priv->keyboard));
 | 
			
		||||
            g_signal_emit_by_name (head->data, "released", priv->keyboard);
 | 
			
		||||
        }
 | 
			
		||||
        g_list_free (list);
 | 
			
		||||
 | 
			
		||||
        g_object_unref (priv->keyboard);
 | 
			
		||||
        priv->keyboard = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (priv->theme) {
 | 
			
		||||
        g_object_unref (priv->theme);
 | 
			
		||||
        priv->theme = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    G_OBJECT_CLASS (eek_gtk_keyboard_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -374,6 +405,7 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    widget_class->realize = eek_gtk_keyboard_real_realize;
 | 
			
		||||
    widget_class->unmap = eek_gtk_keyboard_real_unmap;
 | 
			
		||||
@ -391,25 +423,21 @@ eek_gtk_keyboard_class_init (EekGtkKeyboardClass *klass)
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_gtk_keyboard_set_property;
 | 
			
		||||
    gobject_class->dispose = eek_gtk_keyboard_dispose;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_object ("keyboard",
 | 
			
		||||
                                 "Keyboard",
 | 
			
		||||
                                 "Keyboard",
 | 
			
		||||
                                 EEK_TYPE_KEYBOARD,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_KEYBOARD,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_gtk_keyboard_init (EekGtkKeyboard *self)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    /* Create a default CSS provider and load a style sheet */
 | 
			
		||||
    priv->css_provider = gtk_css_provider_new ();
 | 
			
		||||
    gtk_css_provider_load_from_resource (priv->css_provider,
 | 
			
		||||
        "/sm/puri/squeekboard/style.css");
 | 
			
		||||
 | 
			
		||||
    /* Apply the style to the widget */
 | 
			
		||||
    priv->scontext = gtk_widget_get_style_context (GTK_WIDGET(self));
 | 
			
		||||
    gtk_style_context_add_class (priv->scontext, "keyboard");
 | 
			
		||||
    gtk_style_context_add_provider (priv->scontext,
 | 
			
		||||
        GTK_STYLE_PROVIDER(priv->css_provider),
 | 
			
		||||
        GTK_STYLE_PROVIDER_PRIORITY_USER);
 | 
			
		||||
    gtk_style_context_set_state (priv->scontext, GTK_STATE_FLAG_NORMAL);
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -420,29 +448,61 @@ eek_gtk_keyboard_init (EekGtkKeyboard *self)
 | 
			
		||||
 * Returns: a #GtkWidget
 | 
			
		||||
 */
 | 
			
		||||
GtkWidget *
 | 
			
		||||
eek_gtk_keyboard_new (LevelKeyboard *keyboard)
 | 
			
		||||
eek_gtk_keyboard_new (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboard *ret = EEK_GTK_KEYBOARD(g_object_new (EEK_TYPE_GTK_KEYBOARD, NULL));
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = (EekGtkKeyboardPrivate*)eek_gtk_keyboard_get_instance_private (ret);
 | 
			
		||||
    priv->keyboard = keyboard;
 | 
			
		||||
    return GTK_WIDGET(ret);
 | 
			
		||||
    return g_object_new (EEK_TYPE_GTK_KEYBOARD, "keyboard", keyboard, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
render_pressed_button (GtkWidget *widget,
 | 
			
		||||
                       struct button_place *place)
 | 
			
		||||
magnify_bounds (GtkWidget *self,
 | 
			
		||||
                EekBounds *bounds,
 | 
			
		||||
                EekBounds *large_bounds,
 | 
			
		||||
                gdouble    scale)
 | 
			
		||||
{
 | 
			
		||||
    GtkAllocation allocation;
 | 
			
		||||
    gdouble x, y;
 | 
			
		||||
 | 
			
		||||
    g_assert (scale >= 1.0);
 | 
			
		||||
 | 
			
		||||
    gtk_widget_get_allocation (self, &allocation);
 | 
			
		||||
 | 
			
		||||
    large_bounds->width = bounds->width * scale;
 | 
			
		||||
    large_bounds->height = bounds->height * scale;
 | 
			
		||||
 | 
			
		||||
    x = bounds->x - (large_bounds->width - bounds->width) / 2;
 | 
			
		||||
    y = bounds->y - large_bounds->height;
 | 
			
		||||
 | 
			
		||||
    large_bounds->x = CLAMP(x, 0, allocation.width - large_bounds->width);
 | 
			
		||||
    large_bounds->y = CLAMP(y, 0, allocation.height - large_bounds->height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
render_pressed_key (GtkWidget *widget,
 | 
			
		||||
                    EekKey    *key)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    EekBounds bounds, large_bounds;
 | 
			
		||||
 | 
			
		||||
    GdkWindow         *window  = gtk_widget_get_window (widget);
 | 
			
		||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
			
		||||
    GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
 | 
			
		||||
    cairo_t           *cr      = gdk_drawing_context_get_cairo_context (context);
 | 
			
		||||
    gdouble            scale   = eek_renderer_get_scale (priv->renderer);
 | 
			
		||||
 | 
			
		||||
    eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
 | 
			
		||||
    eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
 | 
			
		||||
    magnify_bounds (widget, &bounds, &large_bounds, 1.5);
 | 
			
		||||
 | 
			
		||||
    cairo_save (cr);
 | 
			
		||||
    cairo_scale (cr, scale, scale);
 | 
			
		||||
    cairo_translate (cr, bounds.x, bounds.y);
 | 
			
		||||
    eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
 | 
			
		||||
    cairo_restore (cr);
 | 
			
		||||
/*
 | 
			
		||||
    cairo_save (cr);
 | 
			
		||||
    cairo_translate (cr, large_bounds.x, large_bounds.y);
 | 
			
		||||
    eek_renderer_render_key (priv->renderer, cr, key, 1.5, TRUE);
 | 
			
		||||
    cairo_restore (cr);
 | 
			
		||||
*/
 | 
			
		||||
    gdk_window_end_draw_frame (window, context);
 | 
			
		||||
 | 
			
		||||
@ -450,17 +510,26 @@ render_pressed_button (GtkWidget *widget,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
render_locked_button (GtkWidget *widget, struct button_place *place)
 | 
			
		||||
render_locked_key (GtkWidget *widget,
 | 
			
		||||
                   EekKey    *key)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    GdkWindow         *window  = gtk_widget_get_window (widget);
 | 
			
		||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
			
		||||
    GdkDrawingContext *context = gdk_window_begin_draw_frame (window, region);
 | 
			
		||||
    cairo_t           *cr      = gdk_drawing_context_get_cairo_context (context);
 | 
			
		||||
    gdouble            scale   = eek_renderer_get_scale (priv->renderer);
 | 
			
		||||
 | 
			
		||||
    eek_renderer_render_button (priv->renderer, cr, place, 1.0, TRUE);
 | 
			
		||||
    eek_renderer_get_key_bounds (priv->renderer, key, &bounds, TRUE);
 | 
			
		||||
 | 
			
		||||
    cairo_save (cr);
 | 
			
		||||
    cairo_scale (cr, scale, scale);
 | 
			
		||||
    cairo_translate (cr, bounds.x, bounds.y);
 | 
			
		||||
    eek_renderer_render_key (priv->renderer, cr, key, 1.0, TRUE);
 | 
			
		||||
    cairo_restore (cr);
 | 
			
		||||
 | 
			
		||||
    gdk_window_end_draw_frame (window, context);
 | 
			
		||||
 | 
			
		||||
@ -468,12 +537,12 @@ render_locked_button (GtkWidget *widget, struct button_place *place)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
render_released_button (GtkWidget *widget,
 | 
			
		||||
                        struct squeek_button *button)
 | 
			
		||||
render_released_key (GtkWidget *widget,
 | 
			
		||||
                     EekKey    *key)
 | 
			
		||||
{
 | 
			
		||||
    (void)button;
 | 
			
		||||
    EekGtkKeyboard        *self = EEK_GTK_KEYBOARD (widget);
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
    EekBounds bounds, large_bounds;
 | 
			
		||||
 | 
			
		||||
    GdkWindow         *window  = gtk_widget_get_window (widget);
 | 
			
		||||
    cairo_region_t    *region  = gdk_window_get_clip_region (window);
 | 
			
		||||
@ -488,8 +557,7 @@ render_released_button (GtkWidget *widget,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_button_pressed (struct squeek_button *button,
 | 
			
		||||
                struct squeek_view *view,
 | 
			
		||||
on_key_pressed (EekKey      *key,
 | 
			
		||||
                EekGtkKeyboard *self)
 | 
			
		||||
{
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
@ -498,14 +566,7 @@ on_button_pressed (struct squeek_button *button,
 | 
			
		||||
    if (!priv->renderer)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    struct button_place place = {
 | 
			
		||||
        .button = button,
 | 
			
		||||
        .row = squeek_view_get_row(view, button),
 | 
			
		||||
    };
 | 
			
		||||
    if (!place.row) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    render_pressed_button (GTK_WIDGET(self), &place);
 | 
			
		||||
    render_pressed_key (GTK_WIDGET(self), key);
 | 
			
		||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
			
		||||
 | 
			
		||||
#if HAVE_LIBCANBERRA
 | 
			
		||||
@ -518,18 +579,16 @@ on_button_pressed (struct squeek_button *button,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_button_released (struct squeek_button *button,
 | 
			
		||||
                 struct squeek_view *view,
 | 
			
		||||
on_key_released (EekKey      *key,
 | 
			
		||||
                 EekGtkKeyboard *self)
 | 
			
		||||
{
 | 
			
		||||
    (void)view;
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    /* renderer may have not been set yet if the widget is a popup */
 | 
			
		||||
    if (!priv->renderer)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    render_released_button (GTK_WIDGET(self), button);
 | 
			
		||||
    render_released_key (GTK_WIDGET(self), key);
 | 
			
		||||
    gtk_widget_queue_draw (GTK_WIDGET(self));
 | 
			
		||||
 | 
			
		||||
#if HAVE_LIBCANBERRA
 | 
			
		||||
@ -540,3 +599,57 @@ on_button_released (struct squeek_button *button,
 | 
			
		||||
                            NULL);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_locked (EekKeyboard *keyboard,
 | 
			
		||||
               EekKey      *key,
 | 
			
		||||
               gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
    GtkWidget *widget = user_data;
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
 | 
			
		||||
 | 
			
		||||
    /* renderer may have not been set yet if the widget is a popup */
 | 
			
		||||
    if (!priv->renderer)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    render_locked_key (widget, key);
 | 
			
		||||
    gtk_widget_queue_draw (widget);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_unlocked (EekKeyboard *keyboard,
 | 
			
		||||
                 EekKey      *key,
 | 
			
		||||
                 gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
    GtkWidget *widget = user_data;
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (user_data);
 | 
			
		||||
 | 
			
		||||
    /* renderer may have not been set yet if the widget is a popup */
 | 
			
		||||
    if (!priv->renderer)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    render_released_key (widget, key);
 | 
			
		||||
    gtk_widget_queue_draw (GTK_WIDGET(widget));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_symbol_index_changed (EekKeyboard *keyboard,
 | 
			
		||||
                         gint         group,
 | 
			
		||||
                         gint         level,
 | 
			
		||||
                         gpointer     user_data)
 | 
			
		||||
{
 | 
			
		||||
    GtkWidget *widget = user_data;
 | 
			
		||||
 | 
			
		||||
    gtk_widget_queue_draw (widget);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
 | 
			
		||||
                            EekTheme       *theme)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_GTK_KEYBOARD(keyboard));
 | 
			
		||||
    g_return_if_fail (EEK_IS_THEME(theme));
 | 
			
		||||
 | 
			
		||||
    EekGtkKeyboardPrivate *priv = eek_gtk_keyboard_get_instance_private (keyboard);
 | 
			
		||||
    priv->theme = g_object_ref (theme);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -45,7 +45,9 @@ struct _EekGtkKeyboardClass
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType      eek_gtk_keyboard_get_type  (void) G_GNUC_CONST;
 | 
			
		||||
GtkWidget *eek_gtk_keyboard_new       (LevelKeyboard *keyboard);
 | 
			
		||||
GtkWidget *eek_gtk_keyboard_new       (EekKeyboard    *keyboard);
 | 
			
		||||
void       eek_gtk_keyboard_set_theme (EekGtkKeyboard *keyboard,
 | 
			
		||||
                                       EekTheme       *theme);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_GTK_KEYBOARD_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										619
									
								
								eek/eek-key.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										619
									
								
								eek/eek-key.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,619 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-key
 | 
			
		||||
 * @short_description: Base class of a key
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekKeyClass class represents a key.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_KEYCODE,
 | 
			
		||||
    PROP_SYMBOL_MATRIX,
 | 
			
		||||
    PROP_COLUMN,
 | 
			
		||||
    PROP_ROW,
 | 
			
		||||
    PROP_OREF,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    LOCKED,
 | 
			
		||||
    UNLOCKED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
typedef struct _EekKeyPrivate
 | 
			
		||||
{
 | 
			
		||||
    guint keycode;
 | 
			
		||||
    EekSymbolMatrix *symbol_matrix;
 | 
			
		||||
    gint column;
 | 
			
		||||
    gint row;
 | 
			
		||||
    gulong oref; // UI outline reference
 | 
			
		||||
    gboolean is_pressed;
 | 
			
		||||
    gboolean is_locked;
 | 
			
		||||
} EekKeyPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (EekKey, eek_key, EEK_TYPE_ELEMENT)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_real_locked (EekKey *self)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    priv->is_locked = TRUE;
 | 
			
		||||
#if DEBUG
 | 
			
		||||
    g_debug ("locked %X", eek_key_get_keycode (self));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_real_unlocked (EekKey *self)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    priv->is_locked = FALSE;
 | 
			
		||||
#if DEBUG
 | 
			
		||||
    g_debug ("unlocked %X", eek_key_get_keycode (self));
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekKey        *self = EEK_KEY (object);
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    eek_symbol_matrix_free (priv->symbol_matrix);
 | 
			
		||||
 | 
			
		||||
    G_OBJECT_CLASS (eek_key_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_set_property (GObject      *object,
 | 
			
		||||
                      guint         prop_id,
 | 
			
		||||
                      const GValue *value,
 | 
			
		||||
                      GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolMatrix *matrix;
 | 
			
		||||
    gint column, row;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_KEYCODE:
 | 
			
		||||
        eek_key_set_keycode (EEK_KEY(object), g_value_get_uint (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_SYMBOL_MATRIX:
 | 
			
		||||
        matrix = g_value_get_boxed (value);
 | 
			
		||||
        eek_key_set_symbol_matrix (EEK_KEY(object), matrix);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_COLUMN:
 | 
			
		||||
        eek_key_get_index (EEK_KEY(object), &column, &row);
 | 
			
		||||
        eek_key_set_index (EEK_KEY(object), g_value_get_int (value), row);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_ROW:
 | 
			
		||||
        eek_key_get_index (EEK_KEY(object), &column, &row);
 | 
			
		||||
        eek_key_set_index (EEK_KEY(object), column, g_value_get_int (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_OREF:
 | 
			
		||||
        eek_key_set_oref (EEK_KEY(object), g_value_get_uint (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_get_property (GObject    *object,
 | 
			
		||||
                      guint       prop_id,
 | 
			
		||||
                      GValue     *value,
 | 
			
		||||
                      GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
    gint column, row;
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_KEYCODE:
 | 
			
		||||
        g_value_set_uint (value, eek_key_get_keycode (EEK_KEY(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_SYMBOL_MATRIX:
 | 
			
		||||
        g_value_set_boxed (value,
 | 
			
		||||
                           eek_key_get_symbol_matrix (EEK_KEY(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_COLUMN:
 | 
			
		||||
        eek_key_get_index (EEK_KEY(object), &column, &row);
 | 
			
		||||
        g_value_set_int (value, column);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_ROW:
 | 
			
		||||
        eek_key_get_index (EEK_KEY(object), &column, &row);
 | 
			
		||||
        g_value_set_int (value, row);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_OREF:
 | 
			
		||||
        g_value_set_uint (value, eek_key_get_oref (EEK_KEY(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_class_init (EekKeyClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec        *pspec;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_key_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_key_get_property;
 | 
			
		||||
    gobject_class->finalize     = eek_key_finalize;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    klass->locked = eek_key_real_locked;
 | 
			
		||||
    klass->unlocked = eek_key_real_unlocked;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey:keycode:
 | 
			
		||||
     *
 | 
			
		||||
     * The keycode of #EekKey.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_uint ("keycode",
 | 
			
		||||
                               "Keycode",
 | 
			
		||||
                               "Keycode of the key",
 | 
			
		||||
                               0, G_MAXUINT, 0,
 | 
			
		||||
                               G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_KEYCODE, pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey:symbol-matrix:
 | 
			
		||||
     *
 | 
			
		||||
     * The symbol matrix of #EekKey.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_boxed ("symbol-matrix",
 | 
			
		||||
                                "Symbol matrix",
 | 
			
		||||
                                "Symbol matrix of the key",
 | 
			
		||||
                                EEK_TYPE_SYMBOL_MATRIX,
 | 
			
		||||
                                G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_SYMBOL_MATRIX, pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey:column:
 | 
			
		||||
     *
 | 
			
		||||
     * The column index of #EekKey in the parent #EekSection.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_int ("column",
 | 
			
		||||
                              "Column",
 | 
			
		||||
                              "Column index of the key in section",
 | 
			
		||||
                              -1, G_MAXINT, -1,
 | 
			
		||||
                              G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_COLUMN, pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey:row:
 | 
			
		||||
     *
 | 
			
		||||
     * The row index of #EekKey in the parent #EekSection.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_int ("row",
 | 
			
		||||
                              "Row",
 | 
			
		||||
                              "Row index of the key in section",
 | 
			
		||||
                              -1, G_MAXINT, -1,
 | 
			
		||||
                              G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_ROW, pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey:oref:
 | 
			
		||||
     *
 | 
			
		||||
     * The outline id of #EekKey.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_ulong ("oref",
 | 
			
		||||
                                "Oref",
 | 
			
		||||
                                "Outline id of the key",
 | 
			
		||||
                                0, G_MAXULONG, 0,
 | 
			
		||||
                                G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_OREF, pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey::locked:
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::locked signal is emitted each time @key is shifted to
 | 
			
		||||
     * the locked state.  The class handler runs before signal
 | 
			
		||||
     * handlers to allow signal handlers to read the status of @key
 | 
			
		||||
     * with eek_key_is_locked().
 | 
			
		||||
     */
 | 
			
		||||
    signals[LOCKED] =
 | 
			
		||||
        g_signal_new (I_("locked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_FIRST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekKeyClass, locked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__VOID,
 | 
			
		||||
                      G_TYPE_NONE, 0);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKey::unlocked:
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::unlocked signal is emitted each time @key is shifted to
 | 
			
		||||
     * the unlocked state.
 | 
			
		||||
     */
 | 
			
		||||
   signals[UNLOCKED] =
 | 
			
		||||
        g_signal_new (I_("unlocked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekKeyClass, unlocked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__VOID,
 | 
			
		||||
                      G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_key_init (EekKey *self)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (self);
 | 
			
		||||
    priv->symbol_matrix = eek_symbol_matrix_new (0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_set_keycode:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @keycode: keycode
 | 
			
		||||
 *
 | 
			
		||||
 * Set the keycode of @key to @keycode.  Since typically the keycode
 | 
			
		||||
 * value is used to find a key in a keyboard by calling
 | 
			
		||||
 * eek_keyboard_find_key_by_keycode, it is not necessarily the same as
 | 
			
		||||
 * the X keycode but it should be unique in the keyboard @key belongs
 | 
			
		||||
 * to.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_key_set_keycode (EekKey *key,
 | 
			
		||||
                     guint   keycode)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY (key));
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    priv->keycode = keycode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_keycode:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Get keycode of @key.
 | 
			
		||||
 * Returns: keycode or %EEK_INVALID_KEYCODE on failure
 | 
			
		||||
 */
 | 
			
		||||
guint
 | 
			
		||||
eek_key_get_keycode (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY (key), EEK_INVALID_KEYCODE);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    return priv->keycode;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_set_symbol_matrix:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @matrix: an #EekSymbolMatrix
 | 
			
		||||
 *
 | 
			
		||||
 * Set the symbol matrix of @key to @matrix.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_key_set_symbol_matrix (EekKey          *key,
 | 
			
		||||
                           EekSymbolMatrix *matrix)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    eek_symbol_matrix_free (priv->symbol_matrix);
 | 
			
		||||
    priv->symbol_matrix = eek_symbol_matrix_copy (matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_symbol_matrix:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Get the symbol matrix of @key.
 | 
			
		||||
 * Returns: (transfer none): #EekSymbolMatrix or %NULL
 | 
			
		||||
 */
 | 
			
		||||
EekSymbolMatrix *
 | 
			
		||||
eek_key_get_symbol_matrix (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY(key), NULL);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    return priv->symbol_matrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_symbol:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Get the current symbol of @key.
 | 
			
		||||
 * Return value: (transfer none): the current #EekSymbol or %NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
EekSymbol *
 | 
			
		||||
eek_key_get_symbol (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    return eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_symbol_with_fallback:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @fallback_group: fallback group index
 | 
			
		||||
 * @fallback_level: fallback level index
 | 
			
		||||
 *
 | 
			
		||||
 * Get the current symbol of @key.
 | 
			
		||||
 * Return value: (transfer none): the current #EekSymbol or %NULL on failure
 | 
			
		||||
 */
 | 
			
		||||
EekSymbol *
 | 
			
		||||
eek_key_get_symbol_with_fallback (EekKey *key,
 | 
			
		||||
                                  gint    fallback_group,
 | 
			
		||||
                                  gint    fallback_level)
 | 
			
		||||
{
 | 
			
		||||
    gint group, level;
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY (key), NULL);
 | 
			
		||||
    g_return_val_if_fail (fallback_group >= 0, NULL);
 | 
			
		||||
    g_return_val_if_fail (fallback_level >= 0, NULL);
 | 
			
		||||
 | 
			
		||||
    eek_element_get_symbol_index (EEK_ELEMENT(key), &group, &level);
 | 
			
		||||
 | 
			
		||||
    if (group < 0 || level < 0) {
 | 
			
		||||
        EekElement *section;
 | 
			
		||||
 | 
			
		||||
        section = eek_element_get_parent (EEK_ELEMENT(key));
 | 
			
		||||
        g_return_val_if_fail (EEK_IS_SECTION (section), NULL);
 | 
			
		||||
 | 
			
		||||
        if (group < 0)
 | 
			
		||||
            group = eek_element_get_group (section);
 | 
			
		||||
 | 
			
		||||
        if (level < 0)
 | 
			
		||||
            level = eek_element_get_level (section);
 | 
			
		||||
 | 
			
		||||
        if (group < 0 || level < 0) {
 | 
			
		||||
            EekElement *keyboard;
 | 
			
		||||
 | 
			
		||||
            keyboard = eek_element_get_parent (section);
 | 
			
		||||
            g_return_val_if_fail (EEK_IS_KEYBOARD (keyboard), NULL);
 | 
			
		||||
 | 
			
		||||
            if (group < 0)
 | 
			
		||||
                group = eek_element_get_group (keyboard);
 | 
			
		||||
            if (level < 0)
 | 
			
		||||
                level = eek_element_get_level (keyboard);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return eek_key_get_symbol_at_index (key,
 | 
			
		||||
                                        group,
 | 
			
		||||
                                        level,
 | 
			
		||||
                                        fallback_group,
 | 
			
		||||
                                        fallback_level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_symbol_at_index:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @group: group index of the symbol matrix
 | 
			
		||||
 * @level: level index of the symbol matrix
 | 
			
		||||
 * @fallback_group: fallback group index
 | 
			
		||||
 * @fallback_level: fallback level index
 | 
			
		||||
 *
 | 
			
		||||
 * Get the symbol at (@group, @level) in the symbol matrix of @key.
 | 
			
		||||
 * Return value: (transfer none): an #EekSymbol at (@group, @level), or %NULL
 | 
			
		||||
 */
 | 
			
		||||
EekSymbol *
 | 
			
		||||
eek_key_get_symbol_at_index (EekKey *key,
 | 
			
		||||
                             gint    group,
 | 
			
		||||
                             gint    level,
 | 
			
		||||
                             gint    fallback_group,
 | 
			
		||||
                             gint    fallback_level)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
    gint num_symbols;
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (fallback_group >= 0, NULL);
 | 
			
		||||
    g_return_val_if_fail (fallback_level >= 0, NULL);
 | 
			
		||||
 | 
			
		||||
    if (group < 0)
 | 
			
		||||
        group = fallback_group;
 | 
			
		||||
    if (level < 0)
 | 
			
		||||
        level = fallback_level;
 | 
			
		||||
 | 
			
		||||
    if (!priv->symbol_matrix)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    num_symbols = priv->symbol_matrix->num_groups *
 | 
			
		||||
        priv->symbol_matrix->num_levels;
 | 
			
		||||
    if (num_symbols == 0)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    if (group >= priv->symbol_matrix->num_groups) {
 | 
			
		||||
        if (fallback_group < 0)
 | 
			
		||||
            return NULL;
 | 
			
		||||
        group = fallback_group;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (level >= priv->symbol_matrix->num_levels) {
 | 
			
		||||
        if (fallback_level < 0)
 | 
			
		||||
            return NULL;
 | 
			
		||||
        level = fallback_level;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return priv->symbol_matrix->data[group * priv->symbol_matrix->num_levels +
 | 
			
		||||
                                     level];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_set_index:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @column: column index of @key in #EekSection
 | 
			
		||||
 * @row: row index of @key in #EekSection
 | 
			
		||||
 *
 | 
			
		||||
 * Set the location of @key in #EekSection with @column and @row.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_key_set_index (EekKey *key,
 | 
			
		||||
                   gint    column,
 | 
			
		||||
                   gint    row)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
			
		||||
    g_return_if_fail (0 <= column);
 | 
			
		||||
    g_return_if_fail (0 <= row);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    if (priv->column != column) {
 | 
			
		||||
        priv->column = column;
 | 
			
		||||
        g_object_notify (G_OBJECT(key), "column");
 | 
			
		||||
    }
 | 
			
		||||
    if (priv->row != row) {
 | 
			
		||||
        priv->row = row;
 | 
			
		||||
        g_object_notify (G_OBJECT(key), "row");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_index:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @column: (allow-none): pointer where the column index of @key in #EekSection will be stored
 | 
			
		||||
 * @row: (allow-none): pointer where the row index of @key in #EekSection will be stored
 | 
			
		||||
 *
 | 
			
		||||
 * Get the location of @key in #EekSection.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_key_get_index (EekKey *key,
 | 
			
		||||
                   gint   *column,
 | 
			
		||||
                   gint   *row)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
			
		||||
    g_return_if_fail (column != NULL || row != NULL);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    if (column != NULL)
 | 
			
		||||
        *column = priv->column;
 | 
			
		||||
    if (row != NULL)
 | 
			
		||||
        *row = priv->row;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_set_oref:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 * @oref: outline id of @key
 | 
			
		||||
 *
 | 
			
		||||
 * Set the outline id of @key to @oref.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_key_set_oref (EekKey *key,
 | 
			
		||||
                  guint   oref)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    if (priv->oref != oref) {
 | 
			
		||||
        priv->oref = oref;
 | 
			
		||||
        g_object_notify (G_OBJECT(key), "oref");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_get_oref:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Get the outline id of @key.
 | 
			
		||||
 * Returns: unsigned integer
 | 
			
		||||
 */
 | 
			
		||||
guint
 | 
			
		||||
eek_key_get_oref (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY (key), 0);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    return priv->oref;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_is_pressed:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Return %TRUE if key is marked as pressed.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
eek_key_is_pressed (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    return priv->is_pressed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_key_is_locked:
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Return %TRUE if key is marked as locked.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
eek_key_is_locked (EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEY(key), FALSE);
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    return priv->is_locked;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eek_key_set_pressed(EekKey *key, gboolean value)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEY(key));
 | 
			
		||||
 | 
			
		||||
    EekKeyPrivate *priv = eek_key_get_instance_private (key);
 | 
			
		||||
 | 
			
		||||
    priv->is_pressed = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
gboolean
 | 
			
		||||
eek_key_has_label(EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbol *symbol = eek_key_get_symbol(key);
 | 
			
		||||
    return (eek_symbol_get_label(symbol) != NULL) ||
 | 
			
		||||
           (eek_symbol_get_icon_name(symbol) != NULL);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										95
									
								
								eek/eek-key.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								eek/eek-key.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,95 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEK_KEY_H
 | 
			
		||||
#define EEK_KEY_H 1
 | 
			
		||||
 | 
			
		||||
#include "eek-element.h"
 | 
			
		||||
#include "eek-symbol-matrix.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_KEY (eek_key_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE(EekKey, eek_key, EEK, KEY, EekElement)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekKeyClass:
 | 
			
		||||
 * @pressed: class handler for #EekKey::pressed signal
 | 
			
		||||
 * @released: class handler for #EekKey::released signal
 | 
			
		||||
 * @locked: class handler for #EekKey::locked signal
 | 
			
		||||
 * @unlocked: class handler for #EekKey::unlocked signal
 | 
			
		||||
 * @cancelled: class handler for #EekKey::cancelled signal
 | 
			
		||||
 * @is_pressed: virtual function for getting whether the key is pressed
 | 
			
		||||
 * @is_locked: virtual function for getting whether the key is locked
 | 
			
		||||
 */
 | 
			
		||||
struct _EekKeyClass
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekElementClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    /* signals */
 | 
			
		||||
    void (* locked)    (EekKey *key);
 | 
			
		||||
    void (* unlocked)  (EekKey *key);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType            eek_key_get_type            (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void             eek_key_set_keycode         (EekKey          *key,
 | 
			
		||||
                                              guint            keycode);
 | 
			
		||||
guint            eek_key_get_keycode         (EekKey          *key);
 | 
			
		||||
void             eek_key_set_symbol_matrix   (EekKey          *key,
 | 
			
		||||
                                              EekSymbolMatrix *matrix);
 | 
			
		||||
EekSymbolMatrix *eek_key_get_symbol_matrix   (EekKey          *key);
 | 
			
		||||
EekSymbol       *eek_key_get_symbol          (EekKey          *key);
 | 
			
		||||
EekSymbol       *eek_key_get_symbol_with_fallback
 | 
			
		||||
                                             (EekKey          *key,
 | 
			
		||||
                                              gint             fallback_group,
 | 
			
		||||
                                              gint             fallback_level);
 | 
			
		||||
EekSymbol       *eek_key_get_symbol_at_index (EekKey          *key,
 | 
			
		||||
                                              gint             group,
 | 
			
		||||
                                              gint             level,
 | 
			
		||||
                                              gint             fallback_group,
 | 
			
		||||
                                              gint             fallback_level);
 | 
			
		||||
 | 
			
		||||
void             eek_key_set_index           (EekKey          *key,
 | 
			
		||||
                                              gint             column,
 | 
			
		||||
                                              gint             row);
 | 
			
		||||
void             eek_key_get_index           (EekKey          *key,
 | 
			
		||||
                                              gint            *column,
 | 
			
		||||
                                              gint            *row);
 | 
			
		||||
 | 
			
		||||
void             eek_key_set_oref            (EekKey          *key,
 | 
			
		||||
                                              guint            oref);
 | 
			
		||||
guint            eek_key_get_oref            (EekKey          *key);
 | 
			
		||||
 | 
			
		||||
gboolean         eek_key_is_pressed          (EekKey          *key);
 | 
			
		||||
gboolean         eek_key_is_locked           (EekKey          *key);
 | 
			
		||||
void             eek_key_set_pressed         (EekKey          *key,
 | 
			
		||||
                                              gboolean         value);
 | 
			
		||||
 | 
			
		||||
gboolean         eek_key_has_label           (EekKey          *key);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_KEY_H */
 | 
			
		||||
@ -30,13 +30,63 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include <glib/gprintf.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eek-marshalers.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
#include "eek-enumtypes.h"
 | 
			
		||||
#include "eekboard/key-emitter.h"
 | 
			
		||||
#include "keymap.h"
 | 
			
		||||
#include "src/keyboard.h"
 | 
			
		||||
#include "src/symbol.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_LAYOUT,
 | 
			
		||||
    PROP_MODIFIER_BEHAVIOR,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KEY_RELEASED,
 | 
			
		||||
    KEY_LOCKED,
 | 
			
		||||
    KEY_UNLOCKED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    VIEW_LETTERS_LOWER,
 | 
			
		||||
    VIEW_LETTERS_UPPER,
 | 
			
		||||
    VIEW_NUMBERS,
 | 
			
		||||
    VIEW_SYMBOLS
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
#define EEK_KEYBOARD_GET_PRIVATE(obj)                                  \
 | 
			
		||||
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), EEK_TYPE_KEYBOARD, EekKeyboardPrivate))
 | 
			
		||||
 | 
			
		||||
struct _EekKeyboardPrivate
 | 
			
		||||
{
 | 
			
		||||
    EekLayout *layout;
 | 
			
		||||
    EekModifierBehavior modifier_behavior;
 | 
			
		||||
    EekModifierType modifiers;
 | 
			
		||||
    unsigned int old_level;
 | 
			
		||||
    GList *pressed_keys;
 | 
			
		||||
    GList *locked_keys;
 | 
			
		||||
    GArray *outline_array;
 | 
			
		||||
 | 
			
		||||
    /* Map key names to key objects: */
 | 
			
		||||
    GHashTable *names;
 | 
			
		||||
 | 
			
		||||
    /* modifiers dynamically assigned at run time */
 | 
			
		||||
    EekModifierType num_lock_mask;
 | 
			
		||||
    EekModifierType alt_gr_mask;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (EekKeyboard, eek_keyboard, EEK_TYPE_CONTAINER);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_BOXED_TYPE(EekModifierKey, eek_modifier_key,
 | 
			
		||||
                    eek_modifier_key_copy, eek_modifier_key_free);
 | 
			
		||||
 | 
			
		||||
EekModifierKey *
 | 
			
		||||
eek_modifier_key_copy (EekModifierKey *modkey)
 | 
			
		||||
@ -47,147 +97,459 @@ eek_modifier_key_copy (EekModifierKey *modkey)
 | 
			
		||||
void
 | 
			
		||||
eek_modifier_key_free (EekModifierKey *modkey)
 | 
			
		||||
{
 | 
			
		||||
    g_object_unref (modkey->key);
 | 
			
		||||
    g_slice_free (EekModifierKey, modkey);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Updates the state of locked keys based on the key that was activated
 | 
			
		||||
/// FIXME: make independent of what the key are named,
 | 
			
		||||
/// and instead refer to the contained symbols
 | 
			
		||||
static guint
 | 
			
		||||
set_key_states (LevelKeyboard    *keyboard,
 | 
			
		||||
                struct squeek_button *button,
 | 
			
		||||
                guint new_level)
 | 
			
		||||
{
 | 
			
		||||
    struct squeek_key *key = squeek_button_get_key(button);
 | 
			
		||||
    // Keys locking rules hardcoded for the time being...
 | 
			
		||||
    const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(key));
 | 
			
		||||
    // Lock the shift whenever it's pressed on the baselevel
 | 
			
		||||
    // TODO: need to lock shift on the destination level
 | 
			
		||||
    if (g_strcmp0(name, "Shift_L") == 0 && keyboard->level == 0) {
 | 
			
		||||
        EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
 | 
			
		||||
        modifier_key->modifiers = 0;
 | 
			
		||||
        modifier_key->button = button;
 | 
			
		||||
        keyboard->locked_buttons =
 | 
			
		||||
            g_list_prepend (keyboard->locked_buttons, modifier_key);
 | 
			
		||||
        squeek_key_set_locked(key, true);
 | 
			
		||||
    }
 | 
			
		||||
    if (keyboard->level == 1) {
 | 
			
		||||
        // Only shift is locked in this state, unlock on any key press
 | 
			
		||||
        for (GList *head = keyboard->locked_buttons; head; ) {
 | 
			
		||||
            EekModifierKey *modifier_key = head->data;
 | 
			
		||||
            GList *next = g_list_next (head);
 | 
			
		||||
            keyboard->locked_buttons =
 | 
			
		||||
                g_list_remove_link (keyboard->locked_buttons, head);
 | 
			
		||||
            squeek_key_set_locked(squeek_button_get_key(modifier_key->button), false);
 | 
			
		||||
            g_list_free1 (head);
 | 
			
		||||
            head = next;
 | 
			
		||||
        }
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    return new_level;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: unhardcode, parse some user information as to which key triggers which view (level)
 | 
			
		||||
static void
 | 
			
		||||
set_level_from_press (LevelKeyboard *keyboard, struct squeek_button *button)
 | 
			
		||||
on_key_locked (EekSection  *section,
 | 
			
		||||
                EekKey      *key,
 | 
			
		||||
                EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit (keyboard, signals[KEY_LOCKED], 0, key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_key_unlocked (EekSection  *section,
 | 
			
		||||
                 EekKey      *key,
 | 
			
		||||
                 EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit (keyboard, signals[KEY_UNLOCKED], 0, key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_symbol_index_changed (EekSection *section,
 | 
			
		||||
                         gint group,
 | 
			
		||||
                         gint level,
 | 
			
		||||
                         EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit_by_name (keyboard, "symbol-index-changed", group, level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
section_child_added_cb (EekContainer *container,
 | 
			
		||||
                        EekElement   *element,
 | 
			
		||||
                        EekKeyboard  *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    const gchar *name = eek_element_get_name(element);
 | 
			
		||||
    g_hash_table_insert (keyboard->priv->names,
 | 
			
		||||
                         (gpointer)name,
 | 
			
		||||
                         element);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
section_child_removed_cb (EekContainer *container,
 | 
			
		||||
                          EekElement   *element,
 | 
			
		||||
                          EekKeyboard  *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    const gchar *name = eek_element_get_name(element);
 | 
			
		||||
    g_hash_table_remove (keyboard->priv->names,
 | 
			
		||||
                         name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EekSection *
 | 
			
		||||
eek_keyboard_real_create_section (EekKeyboard *self)
 | 
			
		||||
{
 | 
			
		||||
    EekSection *section;
 | 
			
		||||
 | 
			
		||||
    section = g_object_new (EEK_TYPE_SECTION, NULL);
 | 
			
		||||
    g_return_val_if_fail (section, NULL);
 | 
			
		||||
 | 
			
		||||
    g_signal_connect (G_OBJECT(section), "child-added",
 | 
			
		||||
                      G_CALLBACK(section_child_added_cb), self);
 | 
			
		||||
 | 
			
		||||
    g_signal_connect (G_OBJECT(section), "child-removed",
 | 
			
		||||
                      G_CALLBACK(section_child_removed_cb), self);
 | 
			
		||||
 | 
			
		||||
    EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
 | 
			
		||||
                                              EEK_ELEMENT(section));
 | 
			
		||||
    return section;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_set_property (GObject      *object,
 | 
			
		||||
                           guint         prop_id,
 | 
			
		||||
                           const GValue *value,
 | 
			
		||||
                           GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_LAYOUT:
 | 
			
		||||
        priv->layout = g_value_get_object (value);
 | 
			
		||||
        if (priv->layout)
 | 
			
		||||
            g_object_ref (priv->layout);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_MODIFIER_BEHAVIOR:
 | 
			
		||||
        eek_keyboard_set_modifier_behavior (EEK_KEYBOARD(object),
 | 
			
		||||
                                            g_value_get_enum (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_get_property (GObject    *object,
 | 
			
		||||
                           guint       prop_id,
 | 
			
		||||
                           GValue     *value,
 | 
			
		||||
                           GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_LAYOUT:
 | 
			
		||||
        g_value_set_object (value, priv->layout);
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_MODIFIER_BEHAVIOR:
 | 
			
		||||
        g_value_set_enum (value,
 | 
			
		||||
                          eek_keyboard_get_modifier_behavior (EEK_KEYBOARD(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_level_from_modifiers (EekKeyboard *self, EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
 | 
			
		||||
 | 
			
		||||
    /* The levels are: 0 Letters, 1 Upper case letters, 2 Numbers, 3 Symbols */
 | 
			
		||||
    guint level = keyboard->level;
 | 
			
		||||
 | 
			
		||||
    /* Use the numbers/letters bit from the old level */
 | 
			
		||||
    gint level = priv->old_level & 2;
 | 
			
		||||
 | 
			
		||||
    /* Handle non-emitting keys */
 | 
			
		||||
    if (button) {
 | 
			
		||||
        const gchar *name = squeek_symbol_get_name(squeek_key_get_symbol(squeek_button_get_key(button)));
 | 
			
		||||
        if (g_strcmp0(name, "show_numbers") == 0) {
 | 
			
		||||
            level = 2;
 | 
			
		||||
        } else if (g_strcmp0(name, "show_letters") == 0) {
 | 
			
		||||
            level = 0;
 | 
			
		||||
        } else if (g_strcmp0(name, "show_symbols") == 0) {
 | 
			
		||||
            level = 3;
 | 
			
		||||
        } else if (g_strcmp0(name, "Shift_L") == 0) {
 | 
			
		||||
            level ^= 1;
 | 
			
		||||
    if (key) {
 | 
			
		||||
        const gchar *name = eek_element_get_name(EEK_ELEMENT(key));
 | 
			
		||||
        if (g_strcmp0(name, "ABC123") == 0)
 | 
			
		||||
            level ^= 2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    level |= ((priv->modifiers & EEK_SHIFT_MASK) ? 1 : 0);
 | 
			
		||||
 | 
			
		||||
    switch (priv->old_level) {
 | 
			
		||||
    case VIEW_LETTERS_UPPER:
 | 
			
		||||
    {
 | 
			
		||||
        /* Redirect upper case letters to numbers instead of symbols, clearing
 | 
			
		||||
           the shift modifier to keep the modifiers in sync with the level */
 | 
			
		||||
        if (level == VIEW_SYMBOLS) {
 | 
			
		||||
            level = VIEW_NUMBERS;
 | 
			
		||||
            priv->modifiers &= ~EEK_SHIFT_MASK;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case VIEW_SYMBOLS:
 | 
			
		||||
    {
 | 
			
		||||
        /* Redirect symbols to lower case letters instead of upper case,
 | 
			
		||||
           clearing the shift modifier to keep the modifiers in sync with the
 | 
			
		||||
           level */
 | 
			
		||||
        if (level == VIEW_LETTERS_UPPER) {
 | 
			
		||||
            level = VIEW_LETTERS_LOWER;
 | 
			
		||||
            priv->modifiers &= ~EEK_SHIFT_MASK;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    case VIEW_LETTERS_LOWER:    /* Direct transitions between views */
 | 
			
		||||
    case VIEW_NUMBERS:
 | 
			
		||||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (level == VIEW_NUMBERS || level == VIEW_SYMBOLS)
 | 
			
		||||
        priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LOCK;
 | 
			
		||||
    else
 | 
			
		||||
        priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_LATCH;
 | 
			
		||||
 | 
			
		||||
    priv->old_level = level;
 | 
			
		||||
    eek_element_set_level (EEK_ELEMENT(self), level);
 | 
			
		||||
 | 
			
		||||
    eek_layout_update_layout(self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_modifiers_with_key (EekKeyboard    *self,
 | 
			
		||||
                        EekKey         *key,
 | 
			
		||||
                        EekModifierType modifiers)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(self);
 | 
			
		||||
    EekModifierType enabled = (priv->modifiers ^ modifiers) & modifiers;
 | 
			
		||||
    EekModifierType disabled = (priv->modifiers ^ modifiers) & priv->modifiers;
 | 
			
		||||
 | 
			
		||||
    if (enabled != 0) {
 | 
			
		||||
        if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
 | 
			
		||||
            EekModifierKey *modifier_key = g_slice_new (EekModifierKey);
 | 
			
		||||
            modifier_key->modifiers = enabled;
 | 
			
		||||
            modifier_key->key = g_object_ref (key);
 | 
			
		||||
            priv->locked_keys =
 | 
			
		||||
                g_list_prepend (priv->locked_keys, modifier_key);
 | 
			
		||||
            g_signal_emit_by_name (modifier_key->key, "locked");
 | 
			
		||||
        }
 | 
			
		||||
    } else {
 | 
			
		||||
        if (priv->modifier_behavior != EEK_MODIFIER_BEHAVIOR_NONE) {
 | 
			
		||||
            GList *head;
 | 
			
		||||
            for (head = priv->locked_keys; head; ) {
 | 
			
		||||
                EekModifierKey *modifier_key = head->data;
 | 
			
		||||
                if (modifier_key->modifiers & disabled) {
 | 
			
		||||
                    GList *next = g_list_next (head);
 | 
			
		||||
                    priv->locked_keys =
 | 
			
		||||
                        g_list_remove_link (priv->locked_keys, head);
 | 
			
		||||
                    g_signal_emit_by_name (modifier_key->key, "unlocked");
 | 
			
		||||
                    g_list_free1 (head);
 | 
			
		||||
                    head = next;
 | 
			
		||||
                } else
 | 
			
		||||
                    head = g_list_next (head);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    keyboard->level = set_key_states(keyboard, button, level);
 | 
			
		||||
 | 
			
		||||
    eek_layout_update_layout(keyboard);
 | 
			
		||||
    priv->modifiers = modifiers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp) {
 | 
			
		||||
    struct squeek_key *key = squeek_button_get_key(button);
 | 
			
		||||
    squeek_key_set_pressed(key, TRUE);
 | 
			
		||||
    keyboard->pressed_buttons = g_list_prepend (keyboard->pressed_buttons, button);
 | 
			
		||||
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp) {
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
 | 
			
		||||
 | 
			
		||||
    struct squeek_symbol *symbol = squeek_key_get_symbol(key);
 | 
			
		||||
    eek_key_set_pressed(key, TRUE);
 | 
			
		||||
    priv->pressed_keys = g_list_prepend (priv->pressed_keys, key);
 | 
			
		||||
 | 
			
		||||
    EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    // Only take action about setting level *after* the key has taken effect, i.e. on release
 | 
			
		||||
    //set_level_from_press (keyboard, key);
 | 
			
		||||
    EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
 | 
			
		||||
    if (priv->modifier_behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
 | 
			
		||||
        set_modifiers_with_key (keyboard, key, priv->modifiers | modifier);
 | 
			
		||||
        set_level_from_modifiers (keyboard, key);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
 | 
			
		||||
 | 
			
		||||
    guint keycode = squeek_key_get_keycode (key);
 | 
			
		||||
    guint keycode = eek_key_get_keycode (key);
 | 
			
		||||
    EekModifierType modifiers = eek_keyboard_get_modifiers (keyboard);
 | 
			
		||||
 | 
			
		||||
    emit_key_activated(keyboard->manager, keyboard, keycode, TRUE, timestamp);
 | 
			
		||||
    emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, TRUE, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eek_keyboard_release_button(LevelKeyboard *keyboard,
 | 
			
		||||
                              struct squeek_button *button,
 | 
			
		||||
void eek_keyboard_release_key( EekKeyboard *keyboard,
 | 
			
		||||
                               EekKey      *key,
 | 
			
		||||
                               guint32      timestamp) {
 | 
			
		||||
    for (GList *head = keyboard->pressed_buttons; head; head = g_list_next (head)) {
 | 
			
		||||
        if (head->data == button) {
 | 
			
		||||
            keyboard->pressed_buttons = g_list_remove_link (keyboard->pressed_buttons, head);
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(keyboard);
 | 
			
		||||
 | 
			
		||||
    for (GList *head = priv->pressed_keys; head; head = g_list_next (head)) {
 | 
			
		||||
        if (head->data == key) {
 | 
			
		||||
            priv->pressed_keys = g_list_remove_link (priv->pressed_keys, head);
 | 
			
		||||
            g_list_free1 (head);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    struct squeek_symbol *symbol = squeek_button_get_symbol(button);
 | 
			
		||||
    EekSymbol *symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    set_level_from_press (keyboard, button);
 | 
			
		||||
    EekModifierType modifier = eek_symbol_get_modifier_mask (symbol);
 | 
			
		||||
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    modifier = eek_symbol_get_modifier_mask (symbol);
 | 
			
		||||
    switch (priv->modifier_behavior) {
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_NONE:
 | 
			
		||||
        set_modifiers_with_key (keyboard, key, priv->modifiers & ~modifier);
 | 
			
		||||
        break;
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_LOCK:
 | 
			
		||||
        priv->modifiers ^= modifier;
 | 
			
		||||
        break;
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_LATCH:
 | 
			
		||||
        if (modifier)
 | 
			
		||||
            set_modifiers_with_key (keyboard, key, priv->modifiers ^ modifier);
 | 
			
		||||
        else
 | 
			
		||||
            set_modifiers_with_key (keyboard, key,
 | 
			
		||||
                                    (priv->modifiers ^ modifier) & modifier);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    set_level_from_modifiers (keyboard, key);
 | 
			
		||||
 | 
			
		||||
    // "Borrowed" from eek-context-service; doesn't influence the state but forwards the event
 | 
			
		||||
 | 
			
		||||
    guint keycode = squeek_key_get_keycode (squeek_button_get_key(button));
 | 
			
		||||
    guint keycode = eek_key_get_keycode (key);
 | 
			
		||||
    guint modifiers = eek_keyboard_get_modifiers (keyboard);
 | 
			
		||||
 | 
			
		||||
    emit_key_activated(keyboard->manager, keyboard, keycode, FALSE, timestamp);
 | 
			
		||||
    emit_key_activated(keyboard->manager, keyboard, keycode, symbol, modifiers, FALSE, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void level_keyboard_deinit(LevelKeyboard *self) {
 | 
			
		||||
    g_hash_table_destroy (self->names);
 | 
			
		||||
    for (guint i = 0; i < self->outline_array->len; i++) {
 | 
			
		||||
        EekOutline *outline = &g_array_index (self->outline_array,
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_dispose (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
 | 
			
		||||
 | 
			
		||||
    if (priv->layout) {
 | 
			
		||||
        g_object_unref (priv->layout);
 | 
			
		||||
        priv->layout = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    G_OBJECT_CLASS (eek_keyboard_parent_class)->dispose (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboardPrivate *priv = EEK_KEYBOARD_GET_PRIVATE(object);
 | 
			
		||||
    guint i;
 | 
			
		||||
 | 
			
		||||
    g_list_free (priv->pressed_keys);
 | 
			
		||||
    g_list_free_full (priv->locked_keys,
 | 
			
		||||
                      (GDestroyNotify) eek_modifier_key_free);
 | 
			
		||||
 | 
			
		||||
    g_hash_table_destroy (priv->names);
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < priv->outline_array->len; i++) {
 | 
			
		||||
        EekOutline *outline = &g_array_index (priv->outline_array,
 | 
			
		||||
                                              EekOutline,
 | 
			
		||||
                                              i);
 | 
			
		||||
        g_slice_free1 (sizeof (EekPoint) * outline->num_points,
 | 
			
		||||
                       outline->points);
 | 
			
		||||
    }
 | 
			
		||||
    g_array_free (self->outline_array, TRUE);
 | 
			
		||||
    for (guint i = 0; i < 4; i++) {
 | 
			
		||||
        // free self->view[i];
 | 
			
		||||
    }
 | 
			
		||||
    g_array_free (priv->outline_array, TRUE);
 | 
			
		||||
        
 | 
			
		||||
    G_OBJECT_CLASS (eek_keyboard_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void level_keyboard_free(LevelKeyboard *self) {
 | 
			
		||||
    level_keyboard_deinit(self);
 | 
			
		||||
    g_free(self);
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_real_child_added (EekContainer *self,
 | 
			
		||||
                               EekElement   *element)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_connect (element, "key-locked",
 | 
			
		||||
                      G_CALLBACK(on_key_locked), self);
 | 
			
		||||
    g_signal_connect (element, "key-unlocked",
 | 
			
		||||
                      G_CALLBACK(on_key_unlocked), self);
 | 
			
		||||
    g_signal_connect (element, "symbol-index-changed",
 | 
			
		||||
                      G_CALLBACK(on_symbol_index_changed), self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void level_keyboard_init(LevelKeyboard *self) {
 | 
			
		||||
    self->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_real_child_removed (EekContainer *self,
 | 
			
		||||
                                 EekElement   *element)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (element, on_key_locked, self);
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (element, on_key_unlocked, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_view *views[4], GHashTable *name_button_hash) {
 | 
			
		||||
    LevelKeyboard *keyboard = g_new0(LevelKeyboard, 1);
 | 
			
		||||
    level_keyboard_init(keyboard);
 | 
			
		||||
    for (uint i = 0; i < 4; i++) {
 | 
			
		||||
        keyboard->views[i] = views[i];
 | 
			
		||||
    }
 | 
			
		||||
    keyboard->manager = manager;
 | 
			
		||||
    keyboard->names = name_button_hash;
 | 
			
		||||
    return keyboard;
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_class_init (EekKeyboardClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
 | 
			
		||||
    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec        *pspec;
 | 
			
		||||
 | 
			
		||||
    klass->create_section = eek_keyboard_real_create_section;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    container_class->child_added = eek_keyboard_real_child_added;
 | 
			
		||||
    container_class->child_removed = eek_keyboard_real_child_removed;
 | 
			
		||||
 | 
			
		||||
    gobject_class->get_property = eek_keyboard_get_property;
 | 
			
		||||
    gobject_class->set_property = eek_keyboard_set_property;
 | 
			
		||||
    gobject_class->dispose = eek_keyboard_dispose;
 | 
			
		||||
    gobject_class->finalize = eek_keyboard_finalize;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKeyboard:layout:
 | 
			
		||||
     *
 | 
			
		||||
     * The layout used to create this #EekKeyboard.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_object ("layout",
 | 
			
		||||
                                 "Layout",
 | 
			
		||||
                                 "Layout used to create the keyboard",
 | 
			
		||||
                                 EEK_TYPE_LAYOUT,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_LAYOUT,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKeyboard:modifier-behavior:
 | 
			
		||||
     *
 | 
			
		||||
     * The modifier handling mode of #EekKeyboard.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_enum ("modifier-behavior",
 | 
			
		||||
                               "Modifier behavior",
 | 
			
		||||
                               "Modifier handling mode of the keyboard",
 | 
			
		||||
                               EEK_TYPE_MODIFIER_BEHAVIOR,
 | 
			
		||||
                               EEK_MODIFIER_BEHAVIOR_NONE,
 | 
			
		||||
                               G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_MODIFIER_BEHAVIOR,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKeyboard::key-locked:
 | 
			
		||||
     * @keyboard: an #EekKeyboard
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::key-locked signal is emitted each time a key in @keyboard
 | 
			
		||||
     * is shifted to the locked state.
 | 
			
		||||
     */
 | 
			
		||||
    signals[KEY_LOCKED] =
 | 
			
		||||
        g_signal_new (I_("key-locked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekKeyboardClass, key_locked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      EEK_TYPE_KEY);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekKeyboard::key-unlocked:
 | 
			
		||||
     * @keyboard: an #EekKeyboard
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::key-unlocked signal is emitted each time a key in @keyboard
 | 
			
		||||
     * is shifted to the unlocked state.
 | 
			
		||||
     */
 | 
			
		||||
    signals[KEY_UNLOCKED] =
 | 
			
		||||
        g_signal_new (I_("key-unlocked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekKeyboardClass, key_unlocked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      EEK_TYPE_KEY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keyboard_init (EekKeyboard *self)
 | 
			
		||||
{
 | 
			
		||||
    self->priv = EEK_KEYBOARD_GET_PRIVATE(self);
 | 
			
		||||
    self->priv->modifier_behavior = EEK_MODIFIER_BEHAVIOR_NONE;
 | 
			
		||||
    self->priv->outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
 | 
			
		||||
    self->priv->names = g_hash_table_new (g_str_hash, g_str_equal);
 | 
			
		||||
    eek_element_set_symbol_index (EEK_ELEMENT(self), 0, 0);
 | 
			
		||||
    self->scale = 1.0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_create_section:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Create an #EekSection instance and append it to @keyboard.  This
 | 
			
		||||
 * function is rarely called by application but called by #EekLayout
 | 
			
		||||
 * implementation.
 | 
			
		||||
 */
 | 
			
		||||
EekSection *
 | 
			
		||||
eek_keyboard_create_section (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
    return EEK_KEYBOARD_GET_CLASS(keyboard)->create_section (keyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -198,11 +560,123 @@ LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek
 | 
			
		||||
 * Find an #EekKey whose name is @name.
 | 
			
		||||
 * Return value: (transfer none): #EekKey whose name is @name
 | 
			
		||||
 */
 | 
			
		||||
struct squeek_button*
 | 
			
		||||
eek_keyboard_find_button_by_name (LevelKeyboard *keyboard,
 | 
			
		||||
EekKey *
 | 
			
		||||
eek_keyboard_find_key_by_name (EekKeyboard *keyboard,
 | 
			
		||||
                               const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    return g_hash_table_lookup (keyboard->names, name);
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
    return g_hash_table_lookup (keyboard->priv->names,
 | 
			
		||||
                                name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_layout:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get the layout used to create @keyboard.
 | 
			
		||||
 * Returns: an #EekLayout
 | 
			
		||||
 */
 | 
			
		||||
EekLayout *
 | 
			
		||||
eek_keyboard_get_layout (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
    return keyboard->priv->layout;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_size:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @width: width of @keyboard
 | 
			
		||||
 * @height: height of @keyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get the size of @keyboard.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_keyboard_get_size (EekKeyboard *keyboard,
 | 
			
		||||
                       gdouble     *width,
 | 
			
		||||
                       gdouble     *height)
 | 
			
		||||
{
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
			
		||||
    *width = bounds.width;
 | 
			
		||||
    *height = bounds.height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_set_modifier_behavior:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @modifier_behavior: modifier behavior of @keyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Set the modifier handling mode of @keyboard.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_keyboard_set_modifier_behavior (EekKeyboard        *keyboard,
 | 
			
		||||
                                    EekModifierBehavior modifier_behavior)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
 | 
			
		||||
    keyboard->priv->modifier_behavior = modifier_behavior;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_modifier_behavior:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get the modifier handling mode of @keyboard.
 | 
			
		||||
 * Returns: #EekModifierBehavior
 | 
			
		||||
 */
 | 
			
		||||
EekModifierBehavior
 | 
			
		||||
eek_keyboard_get_modifier_behavior (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
    return keyboard->priv->modifier_behavior;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_keyboard_set_modifiers (EekKeyboard    *keyboard,
 | 
			
		||||
                            EekModifierType modifiers)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
 | 
			
		||||
    keyboard->priv->modifiers = modifiers;
 | 
			
		||||
    set_level_from_modifiers (keyboard, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_modifiers:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get the current modifier status of @keyboard.
 | 
			
		||||
 * Returns: #EekModifierType
 | 
			
		||||
 */
 | 
			
		||||
EekModifierType
 | 
			
		||||
eek_keyboard_get_modifiers (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
    return keyboard->priv->modifiers;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_add_outline:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @outline: an #EekOutline
 | 
			
		||||
 *
 | 
			
		||||
 * Register an outline of @keyboard.
 | 
			
		||||
 * Returns: an unsigned integer ID of the registered outline, for
 | 
			
		||||
 * later reference
 | 
			
		||||
 */
 | 
			
		||||
guint
 | 
			
		||||
eek_keyboard_add_outline (EekKeyboard *keyboard,
 | 
			
		||||
                          EekOutline  *outline)
 | 
			
		||||
{
 | 
			
		||||
    EekOutline *_outline;
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
 | 
			
		||||
    _outline = eek_outline_copy (outline);
 | 
			
		||||
    g_array_append_val (keyboard->priv->outline_array, *_outline);
 | 
			
		||||
    /* don't use eek_outline_free here, so as to keep _outline->points */
 | 
			
		||||
    g_slice_free (EekOutline, _outline);
 | 
			
		||||
    return keyboard->priv->outline_array->len - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -214,13 +688,117 @@ eek_keyboard_find_button_by_name (LevelKeyboard *keyboard,
 | 
			
		||||
 * Returns: an #EekOutline, which should not be released
 | 
			
		||||
 */
 | 
			
		||||
EekOutline *
 | 
			
		||||
level_keyboard_get_outline (LevelKeyboard *keyboard,
 | 
			
		||||
eek_keyboard_get_outline (EekKeyboard *keyboard,
 | 
			
		||||
                          guint        oref)
 | 
			
		||||
{
 | 
			
		||||
    if (oref > keyboard->outline_array->len)
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
 | 
			
		||||
    if (oref > keyboard->priv->outline_array->len)
 | 
			
		||||
        return NULL;
 | 
			
		||||
 | 
			
		||||
    return &g_array_index (keyboard->outline_array, EekOutline, oref);
 | 
			
		||||
    return &g_array_index (keyboard->priv->outline_array, EekOutline, oref);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_n_outlines:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get the number of outlines defined in @keyboard.
 | 
			
		||||
 * Returns: integer
 | 
			
		||||
 */
 | 
			
		||||
gsize
 | 
			
		||||
eek_keyboard_get_n_outlines (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
    return keyboard->priv->outline_array->len;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_set_num_lock_mask:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @num_lock_mask: an #EekModifierType
 | 
			
		||||
 *
 | 
			
		||||
 * Set modifier mask used as Num_Lock.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_keyboard_set_num_lock_mask (EekKeyboard    *keyboard,
 | 
			
		||||
                                EekModifierType num_lock_mask)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
 | 
			
		||||
    keyboard->priv->num_lock_mask = num_lock_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_num_lock_mask:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get modifier mask used as Num_Lock.
 | 
			
		||||
 * Returns: an #EekModifierType
 | 
			
		||||
 */
 | 
			
		||||
EekModifierType
 | 
			
		||||
eek_keyboard_get_num_lock_mask (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
    return keyboard->priv->num_lock_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_set_alt_gr_mask:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @alt_gr_mask: an #EekModifierType
 | 
			
		||||
 *
 | 
			
		||||
 * Set modifier mask used as Alt_Gr.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_keyboard_set_alt_gr_mask (EekKeyboard    *keyboard,
 | 
			
		||||
                              EekModifierType alt_gr_mask)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_KEYBOARD(keyboard));
 | 
			
		||||
    keyboard->priv->alt_gr_mask = alt_gr_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_alt_gr_mask:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get modifier mask used as Alt_Gr.
 | 
			
		||||
 * Returns: an #EekModifierType
 | 
			
		||||
 */
 | 
			
		||||
EekModifierType
 | 
			
		||||
eek_keyboard_get_alt_gr_mask (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), 0);
 | 
			
		||||
    return keyboard->priv->alt_gr_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_pressed_keys:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get pressed keys.
 | 
			
		||||
 * Returns: (transfer container) (element-type EekKey): A list of
 | 
			
		||||
 * pressed keys.
 | 
			
		||||
 */
 | 
			
		||||
GList *
 | 
			
		||||
eek_keyboard_get_pressed_keys (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
    return g_list_copy (keyboard->priv->pressed_keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_get_locked_keys:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Get locked keys.
 | 
			
		||||
 * Returns: (transfer container) (element-type Eek.ModifierKey): A list
 | 
			
		||||
 * of locked keys.
 | 
			
		||||
 */
 | 
			
		||||
GList *
 | 
			
		||||
eek_keyboard_get_locked_keys (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_KEYBOARD(keyboard), NULL);
 | 
			
		||||
    return g_list_copy (keyboard->priv->locked_keys);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -231,7 +809,7 @@ level_keyboard_get_outline (LevelKeyboard *keyboard,
 | 
			
		||||
 * Returns: a string containing the XKB keymap.
 | 
			
		||||
 */
 | 
			
		||||
gchar *
 | 
			
		||||
eek_keyboard_get_keymap(LevelKeyboard *keyboard)
 | 
			
		||||
eek_keyboard_get_keymap(EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    /* Start the keycodes and symbols sections with their respective headers. */
 | 
			
		||||
    gchar *keycodes = g_strdup(keymap_keycodes_header);
 | 
			
		||||
@ -239,16 +817,14 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
 | 
			
		||||
 | 
			
		||||
    /* Iterate over the keys in the name-to-key hash table. */
 | 
			
		||||
    GHashTableIter iter;
 | 
			
		||||
    gchar *button_name;
 | 
			
		||||
    gpointer button_ptr;
 | 
			
		||||
    g_hash_table_iter_init(&iter, keyboard->names);
 | 
			
		||||
    gpointer key_name, key_ptr;
 | 
			
		||||
    g_hash_table_iter_init(&iter, keyboard->priv->names);
 | 
			
		||||
 | 
			
		||||
    while (g_hash_table_iter_next(&iter, (gpointer)&button_name, &button_ptr)) {
 | 
			
		||||
    while (g_hash_table_iter_next(&iter, &key_name, &key_ptr)) {
 | 
			
		||||
 | 
			
		||||
        gchar *current, *line;
 | 
			
		||||
        struct squeek_button *button = button_ptr;
 | 
			
		||||
        struct squeek_key *key = squeek_button_get_key(button);
 | 
			
		||||
        guint keycode = squeek_key_get_keycode(key);
 | 
			
		||||
        EekKey *key = EEK_KEY(key_ptr);
 | 
			
		||||
        int keycode = eek_key_get_keycode(key);
 | 
			
		||||
 | 
			
		||||
        /* Don't include invalid keycodes in the keymap. */
 | 
			
		||||
        if (keycode == EEK_INVALID_KEYCODE)
 | 
			
		||||
@ -256,19 +832,51 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
 | 
			
		||||
 | 
			
		||||
        /* Append a key name-to-keycode definition to the keycodes section. */
 | 
			
		||||
        current = keycodes;
 | 
			
		||||
        line = g_strdup_printf("        <%s> = %i;\n", (char *)button_name, keycode);
 | 
			
		||||
        line = g_strdup_printf("        <%s> = %i;\n", (char *)key_name, keycode);
 | 
			
		||||
 | 
			
		||||
        keycodes = g_strconcat(current, line, NULL);
 | 
			
		||||
        g_free(line);
 | 
			
		||||
        g_free(current);
 | 
			
		||||
 | 
			
		||||
        // FIXME: free
 | 
			
		||||
        const char *key_str = squeek_key_to_keymap_entry(
 | 
			
		||||
            (char*)button_name,
 | 
			
		||||
            key
 | 
			
		||||
        );
 | 
			
		||||
        /* Find the symbols associated with the key. */
 | 
			
		||||
        EekSymbolMatrix *matrix = eek_key_get_symbol_matrix(key);
 | 
			
		||||
        EekSymbol *syms[4];
 | 
			
		||||
        int i, j;
 | 
			
		||||
 | 
			
		||||
        /* Get the symbols for all the levels defined for the key, then
 | 
			
		||||
           pad it out with the first symbol for all levels up to the fourth. */
 | 
			
		||||
        for (i = 0; i < matrix->num_levels; ++i)
 | 
			
		||||
            syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, i);
 | 
			
		||||
 | 
			
		||||
        while (i < 4) {
 | 
			
		||||
            syms[i] = eek_symbol_matrix_get_symbol(matrix, 0, 0);
 | 
			
		||||
            i++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* The four levels are split into two groups in the keymap.
 | 
			
		||||
           Generate strings for each of these groups, where an empty group is
 | 
			
		||||
           treated specially. */
 | 
			
		||||
 | 
			
		||||
        gchar *groups[2];
 | 
			
		||||
        for (i = 0, j = 0; i < 2; ++i, j += 2) {
 | 
			
		||||
            if (syms[j] && syms[j + 1])
 | 
			
		||||
                groups[i] = g_strjoin(", ", eek_symbol_get_name(syms[j]),
 | 
			
		||||
                                            eek_symbol_get_name(syms[j + 1]),
 | 
			
		||||
                                            NULL);
 | 
			
		||||
            else
 | 
			
		||||
                groups[i] = "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /* Append a key definition to the symbols section. */
 | 
			
		||||
        current = symbols;
 | 
			
		||||
        symbols = g_strconcat(current, key_str, NULL);
 | 
			
		||||
        line = g_strdup_printf("        key <%s> { [ %s ], [ %s ] };\n",
 | 
			
		||||
                               (char *)key_name, groups[0], groups[1]);
 | 
			
		||||
 | 
			
		||||
        g_free(groups[0]);
 | 
			
		||||
        g_free(groups[1]);
 | 
			
		||||
 | 
			
		||||
        symbols = g_strconcat(current, line, NULL);
 | 
			
		||||
        g_free(line);
 | 
			
		||||
        g_free(current);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -282,8 +890,3 @@ eek_keyboard_get_keymap(LevelKeyboard *keyboard)
 | 
			
		||||
    g_free(symbols);
 | 
			
		||||
    return keymap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    return keyboard->views[keyboard->level];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,67 +27,176 @@
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include <xkbcommon/xkbcommon.h>
 | 
			
		||||
#include "eek-container.h"
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
#include "eek-layout.h"
 | 
			
		||||
#include "src/layout.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
struct _EekModifierKey {
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    EekModifierType modifiers;
 | 
			
		||||
    struct squeek_button *button;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _EekModifierKey EekModifierKey;
 | 
			
		||||
#define EEK_TYPE_KEYBOARD (eek_keyboard_get_type())
 | 
			
		||||
#define EEK_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_KEYBOARD, EekKeyboard))
 | 
			
		||||
#define EEK_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_KEYBOARD, EekKeyboardClass))
 | 
			
		||||
#define EEK_IS_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_KEYBOARD))
 | 
			
		||||
#define EEK_IS_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_KEYBOARD))
 | 
			
		||||
#define EEK_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_KEYBOARD, EekKeyboardClass))
 | 
			
		||||
 | 
			
		||||
/// Keyboard state holder
 | 
			
		||||
struct _LevelKeyboard {
 | 
			
		||||
    struct squeek_view *views[4];
 | 
			
		||||
    guint level;
 | 
			
		||||
typedef struct _EekKeyboardClass EekKeyboardClass;
 | 
			
		||||
typedef struct _EekKeyboardPrivate EekKeyboardPrivate;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekKeyboard:
 | 
			
		||||
 *
 | 
			
		||||
 * Contains the state of the physical keyboard.
 | 
			
		||||
 *
 | 
			
		||||
 * Is also a graphical element...
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekKeyboard structure contains only private data and should
 | 
			
		||||
 * only be accessed using the provided API.
 | 
			
		||||
 */
 | 
			
		||||
struct _EekKeyboard
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekContainer parent;
 | 
			
		||||
 | 
			
		||||
    EekKeyboardPrivate *priv;
 | 
			
		||||
    struct xkb_keymap *keymap;
 | 
			
		||||
    int keymap_fd; // keymap formatted as XKB string
 | 
			
		||||
    size_t keymap_len; // length of the data inside keymap_fd
 | 
			
		||||
    GArray *outline_array;
 | 
			
		||||
 | 
			
		||||
    GList *pressed_buttons; // struct squeek_button*
 | 
			
		||||
    GList *locked_buttons; // struct squeek_button*
 | 
			
		||||
 | 
			
		||||
    /* Map button names to button objects: */
 | 
			
		||||
    GHashTable *names;
 | 
			
		||||
 | 
			
		||||
    guint id; // as a key to layout choices
 | 
			
		||||
    double scale;
 | 
			
		||||
 | 
			
		||||
    EekboardContextService *manager; // unowned reference
 | 
			
		||||
};
 | 
			
		||||
typedef struct _LevelKeyboard LevelKeyboard;
 | 
			
		||||
 | 
			
		||||
struct squeek_button *eek_keyboard_find_button_by_name(LevelKeyboard *keyboard,
 | 
			
		||||
                                      const gchar        *name);
 | 
			
		||||
/**
 | 
			
		||||
 * EekKeyboardClass:
 | 
			
		||||
 * @create_section: virtual function for creating a section
 | 
			
		||||
 * @find_key_by_name: virtual function for finding a key in the
 | 
			
		||||
 * keyboard by name
 | 
			
		||||
 * @key_pressed: class handler for #EekKeyboard::key-pressed signal
 | 
			
		||||
 * @key_released: class handler for #EekKeyboard::key-released signal
 | 
			
		||||
 * @key_locked: class handler for #EekKeyboard::key-locked signal
 | 
			
		||||
 * @key_unlocked: class handler for #EekKeyboard::key-unlocked signal
 | 
			
		||||
 * @key_cancelled: class handler for #EekKeyboard::key-cancelled signal
 | 
			
		||||
 */
 | 
			
		||||
struct _EekKeyboardClass
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekContainerClass parent_class;
 | 
			
		||||
 | 
			
		||||
/// Represents the path to the button within a view
 | 
			
		||||
struct button_place {
 | 
			
		||||
    const struct squeek_row *row;
 | 
			
		||||
    const struct squeek_button *button;
 | 
			
		||||
    /* obsolete members moved to EekElement */
 | 
			
		||||
    gpointer set_symbol_index;
 | 
			
		||||
    gpointer get_symbol_index;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    EekSection *(* create_section)      (EekKeyboard *self);
 | 
			
		||||
 | 
			
		||||
    EekKey     *(* find_key_by_name)    (EekKeyboard *self,
 | 
			
		||||
                                         const gchar *name);
 | 
			
		||||
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* obsolete members moved to EekElement */
 | 
			
		||||
    gpointer symbol_index_changed;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    /* signals */
 | 
			
		||||
    void        (* key_locked)          (EekKeyboard *self,
 | 
			
		||||
                                         EekKey      *key);
 | 
			
		||||
    void        (* key_unlocked)        (EekKeyboard *self,
 | 
			
		||||
                                         EekKey      *key);
 | 
			
		||||
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* padding */
 | 
			
		||||
    gpointer pdummy[21];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EekOutline         *level_keyboard_get_outline
 | 
			
		||||
                                     (LevelKeyboard        *keyboard,
 | 
			
		||||
/**
 | 
			
		||||
 * EekModifierKey:
 | 
			
		||||
 * @modifiers: an #EekModifierType which @key triggers
 | 
			
		||||
 * @key: an #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * Entry which associates modifier mask to a key.  This is returned by
 | 
			
		||||
 * eek_keyboard_get_locked_keys().
 | 
			
		||||
 */
 | 
			
		||||
struct _EekModifierKey {
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    EekModifierType modifiers;
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _EekModifierKey EekModifierKey;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
EekKeyboard        *eek_keyboard_new (EekboardContextService *manager,
 | 
			
		||||
                                      EekLayout          *layout,
 | 
			
		||||
                                      gdouble             initial_width,
 | 
			
		||||
                                      gdouble             initial_height);
 | 
			
		||||
GType               eek_keyboard_get_type
 | 
			
		||||
                                     (void) G_GNUC_CONST;
 | 
			
		||||
EekLayout          *eek_keyboard_get_layout
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
void                eek_keyboard_get_size
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      gdouble            *width,
 | 
			
		||||
                                      gdouble            *height);
 | 
			
		||||
void                eek_keyboard_set_size
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      gdouble             width,
 | 
			
		||||
                                      gdouble             height);
 | 
			
		||||
 | 
			
		||||
void                eek_keyboard_set_modifier_behavior
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      EekModifierBehavior modifier_behavior);
 | 
			
		||||
EekModifierBehavior eek_keyboard_get_modifier_behavior
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
void                eek_keyboard_set_modifiers
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      EekModifierType     modifiers);
 | 
			
		||||
EekModifierType     eek_keyboard_get_modifiers
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
EekSection         *eek_keyboard_create_section
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
EekKey             *eek_keyboard_find_key_by_name
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      const gchar        *name);
 | 
			
		||||
 | 
			
		||||
guint               eek_keyboard_add_outline
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      EekOutline         *outline);
 | 
			
		||||
 | 
			
		||||
EekOutline         *eek_keyboard_get_outline
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      guint               oref);
 | 
			
		||||
gsize               eek_keyboard_get_n_outlines
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
void                eek_keyboard_set_num_lock_mask
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      EekModifierType     num_lock_mask);
 | 
			
		||||
EekModifierType     eek_keyboard_get_num_lock_mask
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
void                eek_keyboard_set_alt_gr_mask
 | 
			
		||||
                                     (EekKeyboard        *keyboard,
 | 
			
		||||
                                      EekModifierType     alt_gr_mask);
 | 
			
		||||
EekModifierType     eek_keyboard_get_alt_gr_mask
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
GList              *eek_keyboard_get_pressed_keys
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
GList              *eek_keyboard_get_locked_keys
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
EekModifierKey     *eek_modifier_key_copy
 | 
			
		||||
                                     (EekModifierKey     *modkey);
 | 
			
		||||
void                eek_modifier_key_free
 | 
			
		||||
                                     (EekModifierKey      *modkey);
 | 
			
		||||
 | 
			
		||||
void eek_keyboard_press_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp);
 | 
			
		||||
void eek_keyboard_release_button(LevelKeyboard *keyboard, struct squeek_button *button, guint32 timestamp);
 | 
			
		||||
void eek_keyboard_press_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
			
		||||
void eek_keyboard_release_key(EekKeyboard *keyboard, EekKey *key, guint32 timestamp);
 | 
			
		||||
 | 
			
		||||
gchar *             eek_keyboard_get_keymap
 | 
			
		||||
                                     (LevelKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
struct squeek_view *level_keyboard_current(LevelKeyboard *keyboard);
 | 
			
		||||
LevelKeyboard *level_keyboard_new(EekboardContextService *manager, struct squeek_view *views[], GHashTable *name_button_hash);
 | 
			
		||||
void level_keyboard_deinit(LevelKeyboard *self);
 | 
			
		||||
void level_keyboard_free(LevelKeyboard *self);
 | 
			
		||||
                                     (EekKeyboard        *keyboard);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_KEYBOARD_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										295
									
								
								eek/eek-keysym.c
									
									
									
									
									
								
							
							
						
						
									
										295
									
								
								eek/eek-keysym.c
									
									
									
									
									
								
							@ -25,7 +25,11 @@
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-keysym.h"
 | 
			
		||||
#include "eek-serializable.h"
 | 
			
		||||
 | 
			
		||||
/* modifier keys */
 | 
			
		||||
#define EEK_KEYSYM_Shift_L 0xffe1
 | 
			
		||||
@ -44,22 +48,301 @@
 | 
			
		||||
#define EEK_KEYSYM_Hyper_L 0xffed
 | 
			
		||||
#define EEK_KEYSYM_Hyper_R 0xffee
 | 
			
		||||
 | 
			
		||||
typedef struct _EekKeysymPrivate
 | 
			
		||||
{
 | 
			
		||||
    guint xkeysym;
 | 
			
		||||
} EekKeysymPrivate;
 | 
			
		||||
 | 
			
		||||
struct _EekKeysymEntry {
 | 
			
		||||
    guint xkeysym;
 | 
			
		||||
    const gchar *name;
 | 
			
		||||
    EekSymbolCategory category;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _EekKeysymEntry EekKeysymEntry;
 | 
			
		||||
 | 
			
		||||
#include "eek-special-keysym-entries.h"
 | 
			
		||||
#include "eek-unicode-keysym-entries.h"
 | 
			
		||||
#include "eek-xkeysym-keysym-entries.h"
 | 
			
		||||
 | 
			
		||||
guint32
 | 
			
		||||
eek_keysym_from_name (const gchar *name)
 | 
			
		||||
static void eek_serializable_iface_init (EekSerializableIface *iface);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_EXTENDED (EekKeysym, eek_keysym, EEK_TYPE_SYMBOL,
 | 
			
		||||
			0, /* GTypeFlags */
 | 
			
		||||
			G_ADD_PRIVATE (EekKeysym)
 | 
			
		||||
                        G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
 | 
			
		||||
                                               eek_serializable_iface_init))
 | 
			
		||||
 | 
			
		||||
static EekSerializableIface *eek_keysym_parent_serializable_iface;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keysym_real_serialize (EekSerializable *self,
 | 
			
		||||
                           GVariantBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
    for (uint i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++) {
 | 
			
		||||
        if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0) {
 | 
			
		||||
            return xkeysym_keysym_entries[i].xkeysym;
 | 
			
		||||
        }
 | 
			
		||||
    EekKeysymPrivate *priv = eek_keysym_get_instance_private (
 | 
			
		||||
		    EEK_KEYSYM(self));
 | 
			
		||||
 | 
			
		||||
    eek_keysym_parent_serializable_iface->serialize (self, builder);
 | 
			
		||||
 | 
			
		||||
    g_variant_builder_add (builder, "u", priv->xkeysym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gsize
 | 
			
		||||
eek_keysym_real_deserialize (EekSerializable *self,
 | 
			
		||||
                             GVariant        *variant,
 | 
			
		||||
                             gsize            index)
 | 
			
		||||
{
 | 
			
		||||
    EekKeysymPrivate *priv = eek_keysym_get_instance_private (
 | 
			
		||||
		    EEK_KEYSYM(self));
 | 
			
		||||
 | 
			
		||||
    index = eek_keysym_parent_serializable_iface->deserialize (self,
 | 
			
		||||
                                                               variant,
 | 
			
		||||
                                                               index);
 | 
			
		||||
 | 
			
		||||
    g_variant_get_child (variant, index++, "u", &priv->xkeysym);
 | 
			
		||||
 | 
			
		||||
    return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_serializable_iface_init (EekSerializableIface *iface)
 | 
			
		||||
{
 | 
			
		||||
    eek_keysym_parent_serializable_iface =
 | 
			
		||||
        g_type_interface_peek_parent (iface);
 | 
			
		||||
 | 
			
		||||
    iface->serialize = eek_keysym_real_serialize;
 | 
			
		||||
    iface->deserialize = eek_keysym_real_deserialize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gchar *
 | 
			
		||||
unichar_to_utf8 (gunichar uc)
 | 
			
		||||
{
 | 
			
		||||
    if (g_unichar_isgraph (uc)) {
 | 
			
		||||
        gchar *buf;
 | 
			
		||||
        gint len;
 | 
			
		||||
 | 
			
		||||
        len = g_unichar_to_utf8 (uc, NULL);
 | 
			
		||||
        buf = g_malloc0 (len + 1);
 | 
			
		||||
        g_unichar_to_utf8 (uc, buf);
 | 
			
		||||
        return buf;
 | 
			
		||||
    }
 | 
			
		||||
    return g_strdup ("");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
keysym_entry_compare_by_xkeysym (const void *key0, const void *key1)
 | 
			
		||||
{
 | 
			
		||||
    const EekKeysymEntry *entry0 = key0, *entry1 = key1;
 | 
			
		||||
    return (gint) (entry0->xkeysym - entry1->xkeysym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EekKeysymEntry *
 | 
			
		||||
find_keysym_entry_by_xkeysym (guint xkeysym,
 | 
			
		||||
                              const EekKeysymEntry *entries,
 | 
			
		||||
                              gint num_entries)
 | 
			
		||||
{
 | 
			
		||||
    EekKeysymEntry key;
 | 
			
		||||
 | 
			
		||||
    key.xkeysym = xkeysym;
 | 
			
		||||
    return bsearch (&key, entries, num_entries, sizeof (EekKeysymEntry),
 | 
			
		||||
                    keysym_entry_compare_by_xkeysym);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
get_unichar (guint xkeysym, gunichar *uc) {
 | 
			
		||||
    /* Check for Latin-1 characters (1:1 mapping) */
 | 
			
		||||
    if ((xkeysym >= 0x0020 && xkeysym <= 0x007e) ||
 | 
			
		||||
        (xkeysym >= 0x00a0 && xkeysym <= 0x00ff)) {
 | 
			
		||||
        *uc = xkeysym;
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Also check for directly encoded 24-bit UCS characters:
 | 
			
		||||
     */
 | 
			
		||||
    if ((xkeysym & 0xff000000) == 0x01000000) {
 | 
			
		||||
        *uc = xkeysym & 0x00ffffff;
 | 
			
		||||
        return TRUE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return FALSE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_INLINE_FUNC EekModifierType
 | 
			
		||||
get_modifier_mask (guint xkeysym)
 | 
			
		||||
{
 | 
			
		||||
    switch (xkeysym) {
 | 
			
		||||
    case EEK_KEYSYM_Shift_L:
 | 
			
		||||
    case EEK_KEYSYM_Shift_R:
 | 
			
		||||
    case EEK_KEYSYM_Caps_Lock:
 | 
			
		||||
    case EEK_KEYSYM_Shift_Lock:
 | 
			
		||||
        return EEK_SHIFT_MASK;
 | 
			
		||||
    case EEK_KEYSYM_ISO_Level3_Shift:
 | 
			
		||||
        return EEK_BUTTON1_MASK;
 | 
			
		||||
    case EEK_KEYSYM_Control_L:
 | 
			
		||||
    case EEK_KEYSYM_Control_R:
 | 
			
		||||
        return EEK_CONTROL_MASK;
 | 
			
		||||
    case EEK_KEYSYM_Alt_L:
 | 
			
		||||
    case EEK_KEYSYM_Alt_R:
 | 
			
		||||
        return EEK_MOD1_MASK;
 | 
			
		||||
    case EEK_KEYSYM_Meta_L:
 | 
			
		||||
    case EEK_KEYSYM_Meta_R:
 | 
			
		||||
        return EEK_META_MASK;
 | 
			
		||||
    case EEK_KEYSYM_Super_L:
 | 
			
		||||
    case EEK_KEYSYM_Super_R:
 | 
			
		||||
        return EEK_SUPER_MASK;
 | 
			
		||||
    case EEK_KEYSYM_Hyper_L:
 | 
			
		||||
    case EEK_KEYSYM_Hyper_R:
 | 
			
		||||
        return EEK_HYPER_MASK;
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keysym_class_init (EekKeysymClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_keysym_init (EekKeysym *self)
 | 
			
		||||
{
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keysym_new_with_modifier:
 | 
			
		||||
 * @xkeysym: an X keysym value
 | 
			
		||||
 * @modifier_mask: modifier assigned to @xkeysym
 | 
			
		||||
 *
 | 
			
		||||
 * Create an #EekKeysym with given X keysym value @xkeysym and
 | 
			
		||||
 * modifier @modifier_mask.
 | 
			
		||||
 */
 | 
			
		||||
EekKeysym *
 | 
			
		||||
eek_keysym_new_with_modifier (guint           xkeysym,
 | 
			
		||||
                              EekModifierType modifier_mask)
 | 
			
		||||
{
 | 
			
		||||
    EekKeysym *keysym;
 | 
			
		||||
    EekKeysymPrivate *priv;
 | 
			
		||||
    EekKeysymEntry *special_entry, *xkeysym_entry, *unicode_entry,
 | 
			
		||||
        *unichar_entry;
 | 
			
		||||
    gchar *name, *label;
 | 
			
		||||
    EekSymbolCategory category;
 | 
			
		||||
    gunichar uc;
 | 
			
		||||
 | 
			
		||||
    special_entry =
 | 
			
		||||
        find_keysym_entry_by_xkeysym (xkeysym,
 | 
			
		||||
                                      special_keysym_entries,
 | 
			
		||||
                                      G_N_ELEMENTS(special_keysym_entries));
 | 
			
		||||
    xkeysym_entry =
 | 
			
		||||
        find_keysym_entry_by_xkeysym (xkeysym,
 | 
			
		||||
                                      xkeysym_keysym_entries,
 | 
			
		||||
                                      G_N_ELEMENTS(xkeysym_keysym_entries));
 | 
			
		||||
    unicode_entry =
 | 
			
		||||
        find_keysym_entry_by_xkeysym (xkeysym,
 | 
			
		||||
                                      unicode_keysym_entries,
 | 
			
		||||
                                      G_N_ELEMENTS(unicode_keysym_entries));
 | 
			
		||||
    unichar_entry = NULL;
 | 
			
		||||
    if (get_unichar (xkeysym, &uc)) {
 | 
			
		||||
        unichar_entry = g_slice_new (EekKeysymEntry);
 | 
			
		||||
        unichar_entry->xkeysym = xkeysym;
 | 
			
		||||
        unichar_entry->name = unichar_to_utf8 (uc);
 | 
			
		||||
        unichar_entry->category = EEK_SYMBOL_CATEGORY_LETTER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* name and category */
 | 
			
		||||
    name = NULL;
 | 
			
		||||
    if (xkeysym_entry) {
 | 
			
		||||
        name = g_strdup (xkeysym_entry->name);
 | 
			
		||||
        category = xkeysym_entry->category;
 | 
			
		||||
    } else if (unichar_entry) {
 | 
			
		||||
        name = g_strdup (unichar_entry->name);
 | 
			
		||||
        category = unichar_entry->category;
 | 
			
		||||
    } else if (unicode_entry) {
 | 
			
		||||
        name = g_strdup (unicode_entry->name);
 | 
			
		||||
        category = unicode_entry->category;
 | 
			
		||||
    } else {
 | 
			
		||||
        name = g_strdup ("");
 | 
			
		||||
        category = EEK_SYMBOL_CATEGORY_UNKNOWN;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* label */
 | 
			
		||||
    if (special_entry)
 | 
			
		||||
        label = g_strdup (special_entry->name);
 | 
			
		||||
    else if (unichar_entry)
 | 
			
		||||
        label = g_strdup (unichar_entry->name);
 | 
			
		||||
    else if (unicode_entry)
 | 
			
		||||
        label = g_strdup (unicode_entry->name);
 | 
			
		||||
    else
 | 
			
		||||
        label = g_strdup (name);
 | 
			
		||||
 | 
			
		||||
    keysym = g_object_new (EEK_TYPE_KEYSYM,
 | 
			
		||||
                           "name", name,
 | 
			
		||||
                           "label", label,
 | 
			
		||||
                           "category", category,
 | 
			
		||||
                           "modifier-mask", modifier_mask,
 | 
			
		||||
                           NULL);
 | 
			
		||||
    g_free (name);
 | 
			
		||||
    g_free (label);
 | 
			
		||||
 | 
			
		||||
    if (unichar_entry) {
 | 
			
		||||
        g_free ((gpointer) unichar_entry->name);
 | 
			
		||||
        g_slice_free (EekKeysymEntry, unichar_entry);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    priv = eek_keysym_get_instance_private (keysym);
 | 
			
		||||
    priv->xkeysym = xkeysym;
 | 
			
		||||
 | 
			
		||||
    return keysym;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keysym_new:
 | 
			
		||||
 * @xkeysym: an X keysym value
 | 
			
		||||
 *
 | 
			
		||||
 * Create an #EekKeysym with given X keysym value @xkeysym.
 | 
			
		||||
 */
 | 
			
		||||
EekKeysym *
 | 
			
		||||
eek_keysym_new (guint xkeysym)
 | 
			
		||||
{
 | 
			
		||||
    return eek_keysym_new_with_modifier (xkeysym, get_modifier_mask (xkeysym));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keysym_new_from_name:
 | 
			
		||||
 * @name: an X keysym name
 | 
			
		||||
 *
 | 
			
		||||
 * Create an #EekKeysym with an X keysym value looked up by @name.
 | 
			
		||||
 */
 | 
			
		||||
EekKeysym *
 | 
			
		||||
eek_keysym_new_from_name (const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    gint i;
 | 
			
		||||
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(xkeysym_keysym_entries); i++)
 | 
			
		||||
        if (g_strcmp0 (xkeysym_keysym_entries[i].name, name) == 0)
 | 
			
		||||
            return eek_keysym_new (xkeysym_keysym_entries[i].xkeysym);
 | 
			
		||||
 | 
			
		||||
    // g_warning ("can't find keysym entry for %s", name);
 | 
			
		||||
    return g_object_new (EEK_TYPE_KEYSYM,
 | 
			
		||||
                         "name", name,
 | 
			
		||||
                         "label", name,
 | 
			
		||||
                         "category", EEK_SYMBOL_CATEGORY_UNKNOWN,
 | 
			
		||||
                         "modifier-mask", 0,
 | 
			
		||||
                         NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keysym_get_xkeysym:
 | 
			
		||||
 * @keysym: an #EekKeysym
 | 
			
		||||
 *
 | 
			
		||||
 * Get an X keysym value associated with @keysym
 | 
			
		||||
 */
 | 
			
		||||
guint
 | 
			
		||||
eek_keysym_get_xkeysym (EekKeysym *keysym)
 | 
			
		||||
{
 | 
			
		||||
    EekKeysymPrivate *priv;
 | 
			
		||||
 | 
			
		||||
    g_assert (EEK_IS_KEYSYM(keysym));
 | 
			
		||||
    priv = eek_keysym_get_instance_private (keysym);
 | 
			
		||||
    return priv->xkeysym;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,34 @@
 | 
			
		||||
#ifndef EEK_KEYSYM_H
 | 
			
		||||
#define EEK_KEYSYM_H 1
 | 
			
		||||
 | 
			
		||||
#include "glib.h"
 | 
			
		||||
#include <X11/XKBlib.h>
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
guint32    eek_keysym_from_name         (const gchar    *name);
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EEK_INVALID_KEYSYM:
 | 
			
		||||
 *
 | 
			
		||||
 * Pseudo keysym used for error reporting.
 | 
			
		||||
 */
 | 
			
		||||
#define EEK_INVALID_KEYSYM (0)
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_KEYSYM (eek_keysym_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE (EekKeysym, eek_keysym, EEK, KEYSYM, EekSymbol)
 | 
			
		||||
 | 
			
		||||
struct _EekKeysymClass {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekSymbolClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType      eek_keysym_get_type          (void) G_GNUC_CONST;
 | 
			
		||||
EekKeysym *eek_keysym_new               (guint           xkeysym);
 | 
			
		||||
guint      eek_keysym_get_xkeysym       (EekKeysym      *keysym);
 | 
			
		||||
 | 
			
		||||
EekKeysym *eek_keysym_new_from_name     (const gchar    *name);
 | 
			
		||||
EekKeysym *eek_keysym_new_with_modifier (guint           xkeysym,
 | 
			
		||||
                                         EekModifierType modifier_mask);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif  /* EEK_KEYSYM_H */
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,6 @@
 | 
			
		||||
#include "eek-layout.h"
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eekboard/eekboard-context-service.h"
 | 
			
		||||
#include "eek-xml-layout.h"
 | 
			
		||||
 | 
			
		||||
G_DEFINE_ABSTRACT_TYPE (EekLayout, eek_layout, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
@ -46,8 +45,92 @@ eek_layout_init (EekLayout *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_layout_update_layout(LevelKeyboard *keyboard)
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_new:
 | 
			
		||||
 * @layout: an #EekLayout
 | 
			
		||||
 * @initial_width: initial width of the keyboard
 | 
			
		||||
 * @initial_height: initial height of the keyboard
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new #EekKeyboard based on @layout.
 | 
			
		||||
 */
 | 
			
		||||
EekKeyboard *
 | 
			
		||||
eek_keyboard_new (EekboardContextService *manager,
 | 
			
		||||
                  EekLayout *layout,
 | 
			
		||||
                  gdouble    initial_width,
 | 
			
		||||
                  gdouble    initial_height)
 | 
			
		||||
{
 | 
			
		||||
    squeek_view_place_contents(level_keyboard_current(keyboard), keyboard);
 | 
			
		||||
    g_assert (EEK_IS_LAYOUT(layout));
 | 
			
		||||
    g_assert (EEK_LAYOUT_GET_CLASS(layout)->create_keyboard);
 | 
			
		||||
 | 
			
		||||
    return EEK_LAYOUT_GET_CLASS(layout)->create_keyboard (manager,
 | 
			
		||||
                                                          layout,
 | 
			
		||||
                                                          initial_width,
 | 
			
		||||
                                                          initial_height);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const double section_spacing = 7.0;
 | 
			
		||||
 | 
			
		||||
struct place_data {
 | 
			
		||||
    double desired_width;
 | 
			
		||||
    double current_offset;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
section_placer(EekElement *element, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    struct place_data *data = (struct place_data*)user_data;
 | 
			
		||||
 | 
			
		||||
    EekBounds section_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
			
		||||
    section_bounds.width = data->desired_width;
 | 
			
		||||
    eek_element_set_bounds(element, §ion_bounds);
 | 
			
		||||
 | 
			
		||||
    // Sections are rows now. Gather up all the keys and adjust their bounds.
 | 
			
		||||
    eek_section_place_keys(EEK_SECTION(element), EEK_KEYBOARD(data->keyboard));
 | 
			
		||||
 | 
			
		||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
			
		||||
    section_bounds.y = data->current_offset;
 | 
			
		||||
    eek_element_set_bounds(element, §ion_bounds);
 | 
			
		||||
    data->current_offset += section_bounds.height + section_spacing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
section_counter(EekElement *element, gpointer user_data) {
 | 
			
		||||
 | 
			
		||||
    double *total_height = user_data;
 | 
			
		||||
    EekBounds section_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(element, §ion_bounds);
 | 
			
		||||
    *total_height += section_bounds.height + section_spacing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_layout_place_sections(EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    /* Order rows */
 | 
			
		||||
    // This needs to be done after outlines, because outlines define key sizes
 | 
			
		||||
    // TODO: do this only for rows without bounds
 | 
			
		||||
 | 
			
		||||
    // The keyboard width is given by the user via screen size. The height will be given dynamically.
 | 
			
		||||
    // TODO: calculate max line width beforehand for button centering. Leave keyboard centering to the renderer later
 | 
			
		||||
    EekBounds keyboard_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
			
		||||
 | 
			
		||||
    struct place_data placer_data = {
 | 
			
		||||
        .desired_width = keyboard_bounds.width,
 | 
			
		||||
        .current_offset = 0,
 | 
			
		||||
        .keyboard = keyboard,
 | 
			
		||||
    };
 | 
			
		||||
    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_placer, &placer_data);
 | 
			
		||||
 | 
			
		||||
    double total_height = 0;
 | 
			
		||||
    eek_container_foreach_child(EEK_CONTAINER(keyboard), section_counter, &total_height);
 | 
			
		||||
    keyboard_bounds.height = total_height;
 | 
			
		||||
    eek_element_set_bounds(EEK_ELEMENT(keyboard), &keyboard_bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_layout_update_layout(EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    eek_layout_place_sections(keyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -27,7 +27,6 @@
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
#include "src/layout.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
@ -44,7 +43,7 @@ struct _EekLayoutClass
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    LevelKeyboard* (* create_keyboard) (EekboardContextService *manager,
 | 
			
		||||
    EekKeyboard* (* create_keyboard) (EekboardContextService *manager,
 | 
			
		||||
                                      EekLayout *self,
 | 
			
		||||
                                      gdouble    initial_width,
 | 
			
		||||
                                      gdouble    initial_height);
 | 
			
		||||
@ -56,14 +55,9 @@ struct _EekLayoutClass
 | 
			
		||||
 | 
			
		||||
GType        eek_layout_get_type  (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void         eek_layout_place_rows(LevelKeyboard *keyboard, struct squeek_view *level);
 | 
			
		||||
void         eek_layout_place_sections(EekKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
void         eek_layout_update_layout(LevelKeyboard *keyboard);
 | 
			
		||||
void         eek_layout_update_layout(EekKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
LevelKeyboard *
 | 
			
		||||
level_keyboard_from_layout (EekLayout *layout,
 | 
			
		||||
                  gdouble    initial_width,
 | 
			
		||||
                  gdouble    initial_height);
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_LAYOUT_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								eek/eek-marshalers.list
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								eek/eek-marshalers.list
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
VOID:INT,INT
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -21,11 +21,12 @@
 | 
			
		||||
#ifndef EEK_RENDERER_H
 | 
			
		||||
#define EEK_RENDERER_H 1
 | 
			
		||||
 | 
			
		||||
#include <gtk/gtk.h>
 | 
			
		||||
#include <pango/pangocairo.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eek-keysym.h"
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
#include "eek-theme.h"
 | 
			
		||||
#include "eek-theme-context.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
@ -36,9 +37,19 @@ struct _EekRendererClass
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
    void             (* render_button)         (EekRenderer *self,
 | 
			
		||||
    void             (* render_key_label)   (EekRenderer *self,
 | 
			
		||||
                                             PangoLayout *layout,
 | 
			
		||||
                                             EekKey      *key);
 | 
			
		||||
 | 
			
		||||
    void             (* render_key_outline) (EekRenderer *self,
 | 
			
		||||
                                             cairo_t     *cr,
 | 
			
		||||
                                             struct button_place *place,
 | 
			
		||||
                                             EekKey      *key,
 | 
			
		||||
                                             gdouble      scale,
 | 
			
		||||
                                             gboolean     rotate);
 | 
			
		||||
 | 
			
		||||
    void             (* render_key)         (EekRenderer *self,
 | 
			
		||||
                                             cairo_t     *cr,
 | 
			
		||||
                                             EekKey      *key,
 | 
			
		||||
                                             gdouble      scale,
 | 
			
		||||
                                             gboolean     rotate);
 | 
			
		||||
 | 
			
		||||
@ -56,9 +67,8 @@ struct _EekRendererClass
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType            eek_renderer_get_type         (void) G_GNUC_CONST;
 | 
			
		||||
EekRenderer     *eek_renderer_new              (LevelKeyboard     *keyboard,
 | 
			
		||||
                                                PangoContext    *pcontext,
 | 
			
		||||
                                                GtkStyleContext *scontext);
 | 
			
		||||
EekRenderer     *eek_renderer_new              (EekKeyboard     *keyboard,
 | 
			
		||||
                                                PangoContext    *pcontext);
 | 
			
		||||
void             eek_renderer_set_allocation_size
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                gdouble          width,
 | 
			
		||||
@ -66,8 +76,8 @@ void             eek_renderer_set_allocation_size
 | 
			
		||||
void             eek_renderer_get_size         (EekRenderer     *renderer,
 | 
			
		||||
                                                gdouble         *width,
 | 
			
		||||
                                                gdouble         *height);
 | 
			
		||||
void             eek_renderer_get_button_bounds   (EekRenderer     *renderer,
 | 
			
		||||
                                                struct button_place *button,
 | 
			
		||||
void             eek_renderer_get_key_bounds   (EekRenderer     *renderer,
 | 
			
		||||
                                                EekKey          *key,
 | 
			
		||||
                                                EekBounds       *bounds,
 | 
			
		||||
                                                gboolean         rotate);
 | 
			
		||||
 | 
			
		||||
@ -77,9 +87,20 @@ void             eek_renderer_set_scale_factor (EekRenderer     *renderer,
 | 
			
		||||
 | 
			
		||||
PangoLayout     *eek_renderer_create_pango_layout
 | 
			
		||||
                                               (EekRenderer     *renderer);
 | 
			
		||||
void             eek_renderer_render_button       (EekRenderer     *renderer,
 | 
			
		||||
void             eek_renderer_render_key_label (EekRenderer     *renderer,
 | 
			
		||||
                                                PangoLayout     *layout,
 | 
			
		||||
                                                EekKey          *key);
 | 
			
		||||
 | 
			
		||||
void             eek_renderer_render_key_outline
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                cairo_t         *cr,
 | 
			
		||||
                                                struct button_place *place,
 | 
			
		||||
                                                EekKey          *key,
 | 
			
		||||
                                                gdouble          scale,
 | 
			
		||||
                                                gboolean         rotate);
 | 
			
		||||
 | 
			
		||||
void             eek_renderer_render_key       (EekRenderer     *renderer,
 | 
			
		||||
                                                cairo_t         *cr,
 | 
			
		||||
                                                EekKey          *key,
 | 
			
		||||
                                                gdouble          scale,
 | 
			
		||||
                                                gboolean         rotate);
 | 
			
		||||
 | 
			
		||||
@ -99,18 +120,33 @@ void             eek_renderer_set_default_background_color
 | 
			
		||||
                                                const EekColor  *color);
 | 
			
		||||
void             eek_renderer_get_foreground_color
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                GtkStyleContext *context,
 | 
			
		||||
                                                EekElement      *element,
 | 
			
		||||
                                                EekColor        *color);
 | 
			
		||||
void             eek_renderer_get_background_color
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                EekElement      *element,
 | 
			
		||||
                                                EekColor        *color);
 | 
			
		||||
void             eek_renderer_get_background_gradient
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                EekElement      *element,
 | 
			
		||||
                                                EekGradientType *type,
 | 
			
		||||
                                                EekColor        *start,
 | 
			
		||||
                                                EekColor        *end);
 | 
			
		||||
void             eek_renderer_set_border_width (EekRenderer     *renderer,
 | 
			
		||||
                                                gdouble          border_width);
 | 
			
		||||
struct squeek_button *eek_renderer_find_button_by_position(EekRenderer     *renderer, struct squeek_view *view,
 | 
			
		||||
EekKey          *eek_renderer_find_key_by_position
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                gdouble          x,
 | 
			
		||||
                                                gdouble          y);
 | 
			
		||||
void             eek_renderer_apply_transformation_for_button
 | 
			
		||||
void             eek_renderer_apply_transformation_for_key
 | 
			
		||||
                                               (EekRenderer     *renderer,
 | 
			
		||||
                                                cairo_t         *cr, struct button_place *place,
 | 
			
		||||
                                                cairo_t         *cr,
 | 
			
		||||
                                                EekKey          *key,
 | 
			
		||||
                                                gdouble          scale,
 | 
			
		||||
                                                gboolean         rotate);
 | 
			
		||||
 | 
			
		||||
void             eek_renderer_set_theme        (EekRenderer     *renderer,
 | 
			
		||||
                                                EekTheme        *theme);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_RENDERER_H */
 | 
			
		||||
 | 
			
		||||
@ -18,12 +18,491 @@
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-section
 | 
			
		||||
 * @short_description: Base class of a section
 | 
			
		||||
 * @see_also: #EekKey
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekSectionClass class represents a section, which consists
 | 
			
		||||
 * of one or more keys of the #EekKeyClass class.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
EekBounds eek_get_outline_size(LevelKeyboard *keyboard, uint32_t oref) {
 | 
			
		||||
    EekOutline *outline = level_keyboard_get_outline (keyboard, oref);
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_ANGLE,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    KEY_LOCKED,
 | 
			
		||||
    KEY_UNLOCKED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
struct _EekRow
 | 
			
		||||
{
 | 
			
		||||
    gint num_columns;
 | 
			
		||||
    EekOrientation orientation;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _EekRow EekRow;
 | 
			
		||||
 | 
			
		||||
typedef struct _EekSectionPrivate
 | 
			
		||||
{
 | 
			
		||||
    gint angle;
 | 
			
		||||
    GSList *rows;
 | 
			
		||||
    EekModifierType modifiers;
 | 
			
		||||
} EekSectionPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (EekSection, eek_section, EEK_TYPE_CONTAINER)
 | 
			
		||||
 | 
			
		||||
static gint
 | 
			
		||||
eek_section_real_get_n_rows (EekSection *self)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    return g_slist_length (priv->rows);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_add_row (EekSection    *self,
 | 
			
		||||
                          gint           num_columns,
 | 
			
		||||
                          EekOrientation orientation)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    EekRow *row;
 | 
			
		||||
 | 
			
		||||
    row = g_slice_new (EekRow);
 | 
			
		||||
    row->num_columns = num_columns;
 | 
			
		||||
    row->orientation = orientation;
 | 
			
		||||
    priv->rows = g_slist_append (priv->rows, row);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_get_row (EekSection     *self,
 | 
			
		||||
                          gint            index,
 | 
			
		||||
                          gint           *num_columns,
 | 
			
		||||
                          EekOrientation *orientation)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    EekRow *row;
 | 
			
		||||
 | 
			
		||||
    row = g_slist_nth_data (priv->rows, index);
 | 
			
		||||
    g_return_if_fail (row);
 | 
			
		||||
    if (num_columns)
 | 
			
		||||
        *num_columns = row->num_columns;
 | 
			
		||||
    if (orientation)
 | 
			
		||||
        *orientation = row->orientation;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_locked (EekKey     *key,
 | 
			
		||||
           EekSection *section)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit (section, signals[KEY_LOCKED], 0, key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
on_unlocked (EekKey     *key,
 | 
			
		||||
             EekSection *section)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_emit (section, signals[KEY_UNLOCKED], 0, key);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static EekKey *
 | 
			
		||||
eek_section_real_create_key (EekSection *self,
 | 
			
		||||
                             const gchar *name,
 | 
			
		||||
                             gint        keycode,
 | 
			
		||||
                             gint        column_index,
 | 
			
		||||
                             gint        row_index)
 | 
			
		||||
{
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
    gint num_rows;
 | 
			
		||||
    EekRow *row;
 | 
			
		||||
 | 
			
		||||
    num_rows = eek_section_get_n_rows (self);
 | 
			
		||||
    g_return_val_if_fail (0 <= row_index && row_index < num_rows, NULL);
 | 
			
		||||
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    row = g_slist_nth_data (priv->rows, row_index);
 | 
			
		||||
    if (row->num_columns < column_index + 1)
 | 
			
		||||
        row->num_columns = column_index + 1;
 | 
			
		||||
 | 
			
		||||
    key = g_object_new (EEK_TYPE_KEY,
 | 
			
		||||
                        "name", name,
 | 
			
		||||
                        "keycode", keycode,
 | 
			
		||||
                        "column", column_index,
 | 
			
		||||
                        "row", row_index,
 | 
			
		||||
                        NULL);
 | 
			
		||||
    g_return_val_if_fail (key, NULL);
 | 
			
		||||
 | 
			
		||||
    EEK_CONTAINER_GET_CLASS(self)->add_child (EEK_CONTAINER(self),
 | 
			
		||||
                                              EEK_ELEMENT(key));
 | 
			
		||||
 | 
			
		||||
    return key;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
set_level_from_modifiers (EekSection *self)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekModifierType num_lock_mask;
 | 
			
		||||
    gint level = -1;
 | 
			
		||||
 | 
			
		||||
    keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
 | 
			
		||||
    num_lock_mask = eek_keyboard_get_num_lock_mask (keyboard);
 | 
			
		||||
    if (priv->modifiers & num_lock_mask)
 | 
			
		||||
        level = 1;
 | 
			
		||||
    eek_element_set_level (EEK_ELEMENT(self), level);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_key_pressed (EekSection *self, EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    EekSymbol *symbol;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekModifierBehavior behavior;
 | 
			
		||||
    EekModifierType modifier;
 | 
			
		||||
 | 
			
		||||
    symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
 | 
			
		||||
    behavior = eek_keyboard_get_modifier_behavior (keyboard);
 | 
			
		||||
    modifier = eek_symbol_get_modifier_mask (symbol);
 | 
			
		||||
    if (behavior == EEK_MODIFIER_BEHAVIOR_NONE) {
 | 
			
		||||
        priv->modifiers |= modifier;
 | 
			
		||||
        set_level_from_modifiers (self);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_key_released (EekSection *self, EekKey *key)
 | 
			
		||||
{
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    EekSymbol *symbol;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekModifierBehavior behavior;
 | 
			
		||||
    EekModifierType modifier;
 | 
			
		||||
 | 
			
		||||
    symbol = eek_key_get_symbol_with_fallback (key, 0, 0);
 | 
			
		||||
    if (!symbol)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    keyboard = EEK_KEYBOARD(eek_element_get_parent (EEK_ELEMENT(self)));
 | 
			
		||||
    behavior = eek_keyboard_get_modifier_behavior (keyboard);
 | 
			
		||||
    modifier = eek_symbol_get_modifier_mask (symbol);
 | 
			
		||||
    switch (behavior) {
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_NONE:
 | 
			
		||||
        priv->modifiers &= ~modifier;
 | 
			
		||||
        break;
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_LOCK:
 | 
			
		||||
        priv->modifiers ^= modifier;
 | 
			
		||||
        break;
 | 
			
		||||
    case EEK_MODIFIER_BEHAVIOR_LATCH:
 | 
			
		||||
        priv->modifiers = (priv->modifiers ^ modifier) & modifier;
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    set_level_from_modifiers (self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekSection        *self = EEK_SECTION (object);
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (self);
 | 
			
		||||
    GSList *head;
 | 
			
		||||
 | 
			
		||||
    for (head = priv->rows; head; head = g_slist_next (head))
 | 
			
		||||
        g_slice_free (EekRow, head->data);
 | 
			
		||||
    g_slist_free (priv->rows);
 | 
			
		||||
 | 
			
		||||
    G_OBJECT_CLASS (eek_section_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_set_property (GObject      *object,
 | 
			
		||||
                          guint         prop_id,
 | 
			
		||||
                          const GValue *value,
 | 
			
		||||
                          GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_ANGLE:
 | 
			
		||||
        eek_section_set_angle (EEK_SECTION(object),
 | 
			
		||||
                               g_value_get_int (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_get_property (GObject    *object,
 | 
			
		||||
                          guint       prop_id,
 | 
			
		||||
                          GValue     *value,
 | 
			
		||||
                          GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_ANGLE:
 | 
			
		||||
        g_value_set_int (value, eek_section_get_angle (EEK_SECTION(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_child_added (EekContainer *self,
 | 
			
		||||
                              EekElement   *element)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_connect (element, "locked", G_CALLBACK(on_locked), self);
 | 
			
		||||
    g_signal_connect (element, "unlocked", G_CALLBACK(on_unlocked), self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_real_child_removed (EekContainer *self,
 | 
			
		||||
                                EekElement   *element)
 | 
			
		||||
{
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (element, on_locked, self);
 | 
			
		||||
    g_signal_handlers_disconnect_by_func (element, on_unlocked, self);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_class_init (EekSectionClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    EekContainerClass *container_class = EEK_CONTAINER_CLASS (klass);
 | 
			
		||||
    GObjectClass      *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec        *pspec;
 | 
			
		||||
 | 
			
		||||
    klass->get_n_rows = eek_section_real_get_n_rows;
 | 
			
		||||
    klass->add_row = eek_section_real_add_row;
 | 
			
		||||
    klass->get_row = eek_section_real_get_row;
 | 
			
		||||
    klass->create_key = eek_section_real_create_key;
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    klass->key_pressed = eek_section_real_key_pressed;
 | 
			
		||||
    klass->key_released = eek_section_real_key_released;
 | 
			
		||||
 | 
			
		||||
    container_class->child_added = eek_section_real_child_added;
 | 
			
		||||
    container_class->child_removed = eek_section_real_child_removed;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_section_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_section_get_property;
 | 
			
		||||
    gobject_class->finalize     = eek_section_finalize;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekSection:angle:
 | 
			
		||||
     *
 | 
			
		||||
     * The rotation angle of #EekSection.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_int ("angle",
 | 
			
		||||
                              "Angle",
 | 
			
		||||
                              "Rotation angle of the section",
 | 
			
		||||
                              -360, 360, 0,
 | 
			
		||||
                              G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_ANGLE,
 | 
			
		||||
                                     pspec);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekSection::key-locked:
 | 
			
		||||
     * @section: an #EekSection
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::key-locked signal is emitted each time a key in @section
 | 
			
		||||
     * is shifted to the locked state.
 | 
			
		||||
     */
 | 
			
		||||
    signals[KEY_LOCKED] =
 | 
			
		||||
        g_signal_new (I_("key-locked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekSectionClass, key_locked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      EEK_TYPE_KEY);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekSection::key-unlocked:
 | 
			
		||||
     * @section: an #EekSection
 | 
			
		||||
     * @key: an #EekKey
 | 
			
		||||
     *
 | 
			
		||||
     * The ::key-unlocked signal is emitted each time a key in @section
 | 
			
		||||
     * is shifted to the unlocked state.
 | 
			
		||||
     */
 | 
			
		||||
    signals[KEY_UNLOCKED] =
 | 
			
		||||
        g_signal_new (I_("key-unlocked"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekSectionClass, key_unlocked),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      g_cclosure_marshal_VOID__OBJECT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      1,
 | 
			
		||||
                      EEK_TYPE_KEY);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_section_init (EekSection *self)
 | 
			
		||||
{
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_set_angle:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 * @angle: rotation angle
 | 
			
		||||
 *
 | 
			
		||||
 * Set rotation angle of @section to @angle.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_section_set_angle (EekSection  *section,
 | 
			
		||||
                       gint         angle)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_SECTION(section));
 | 
			
		||||
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (section);
 | 
			
		||||
 | 
			
		||||
    if (priv->angle != angle) {
 | 
			
		||||
        priv->angle = angle;
 | 
			
		||||
        g_object_notify (G_OBJECT(section), "angle");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_get_angle:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 *
 | 
			
		||||
 * Get rotation angle of @section.
 | 
			
		||||
 */
 | 
			
		||||
gint
 | 
			
		||||
eek_section_get_angle (EekSection *section)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SECTION(section), -1);
 | 
			
		||||
 | 
			
		||||
    EekSectionPrivate *priv = eek_section_get_instance_private (section);
 | 
			
		||||
 | 
			
		||||
    return priv->angle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_get_n_rows:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 *
 | 
			
		||||
 * Get the number of rows in @section.
 | 
			
		||||
 */
 | 
			
		||||
gint
 | 
			
		||||
eek_section_get_n_rows (EekSection *section)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SECTION(section), -1);
 | 
			
		||||
    return EEK_SECTION_GET_CLASS(section)->get_n_rows (section);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_add_row:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 * @num_columns: the number of column in the row
 | 
			
		||||
 * @orientation: #EekOrientation of the row
 | 
			
		||||
 *
 | 
			
		||||
 * Add a row which has @num_columns columns and whose orientation is
 | 
			
		||||
 * @orientation to @section.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_section_add_row (EekSection    *section,
 | 
			
		||||
                     gint           num_columns,
 | 
			
		||||
                     EekOrientation orientation)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_SECTION(section));
 | 
			
		||||
    EEK_SECTION_GET_CLASS(section)->add_row (section,
 | 
			
		||||
                                             num_columns,
 | 
			
		||||
                                             orientation);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_get_row:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 * @index: the index of row
 | 
			
		||||
 * @num_columns: pointer where the number of column in the row will be stored
 | 
			
		||||
 * @orientation: pointer where #EekOrientation of the row will be stored
 | 
			
		||||
 *
 | 
			
		||||
 * Get the information about the @index-th row in @section.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_section_get_row (EekSection     *section,
 | 
			
		||||
                     gint            index,
 | 
			
		||||
                     gint           *num_columns,
 | 
			
		||||
                     EekOrientation *orientation)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_SECTION(section));
 | 
			
		||||
    EEK_SECTION_GET_CLASS(section)->get_row (section,
 | 
			
		||||
                                             index,
 | 
			
		||||
                                             num_columns,
 | 
			
		||||
                                             orientation);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_section_create_key:
 | 
			
		||||
 * @section: an #EekSection
 | 
			
		||||
 * @name: a name
 | 
			
		||||
 * @keycode: a keycode
 | 
			
		||||
 * @column: the column index of the key
 | 
			
		||||
 * @row: the row index of the key
 | 
			
		||||
 *
 | 
			
		||||
 * Create an #EekKey instance and append it to @section.  This
 | 
			
		||||
 * function is rarely called by application but called by #EekLayout
 | 
			
		||||
 * implementation.
 | 
			
		||||
 */
 | 
			
		||||
EekKey *
 | 
			
		||||
eek_section_create_key (EekSection *section,
 | 
			
		||||
                        const gchar *name,
 | 
			
		||||
                        gint        keycode,
 | 
			
		||||
                        gint        column,
 | 
			
		||||
                        gint        row)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SECTION(section), NULL);
 | 
			
		||||
    return EEK_SECTION_GET_CLASS(section)->create_key (section,
 | 
			
		||||
                                                       name,
 | 
			
		||||
                                                       keycode,
 | 
			
		||||
                                                       column,
 | 
			
		||||
                                                       row);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const double keyspacing = 4.0;
 | 
			
		||||
 | 
			
		||||
struct keys_info {
 | 
			
		||||
    uint count;
 | 
			
		||||
    double total_width;
 | 
			
		||||
    double biggest_height;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
keysizer(EekElement *element, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekKey *key = EEK_KEY(element);
 | 
			
		||||
 | 
			
		||||
    EekKeyboard *keyboard = EEK_KEYBOARD(user_data);
 | 
			
		||||
    uint oref = eek_key_get_oref (key);
 | 
			
		||||
    EekOutline *outline = eek_keyboard_get_outline (keyboard, oref);
 | 
			
		||||
    if (outline && outline->num_points > 0) {
 | 
			
		||||
        double minx = outline->points[0].x;
 | 
			
		||||
        double maxx = minx;
 | 
			
		||||
@ -43,14 +522,65 @@ EekBounds eek_get_outline_size(LevelKeyboard *keyboard, uint32_t oref) {
 | 
			
		||||
                maxy = p.y;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        EekBounds key_bounds = {
 | 
			
		||||
            .height = maxy - miny,
 | 
			
		||||
            .width = maxx - minx,
 | 
			
		||||
            .x = 0,
 | 
			
		||||
            .y = 0,
 | 
			
		||||
        };
 | 
			
		||||
        return key_bounds;
 | 
			
		||||
        EekBounds key_bounds = {0};
 | 
			
		||||
        eek_element_get_bounds(element, &key_bounds);
 | 
			
		||||
        key_bounds.height = maxy - miny;
 | 
			
		||||
        key_bounds.width = maxx - minx;
 | 
			
		||||
        eek_element_set_bounds(element, &key_bounds);
 | 
			
		||||
    }
 | 
			
		||||
    EekBounds bounds = {0, 0, 0, 0};
 | 
			
		||||
    return bounds;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
keycounter (EekElement *element, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekKey *key = EEK_KEY(element);
 | 
			
		||||
 | 
			
		||||
    /* Skip keys without labels for the current level. This causes those
 | 
			
		||||
       keys to be hidden in the visible layout. */
 | 
			
		||||
    if (!eek_key_has_label(key))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    struct keys_info *data = user_data;
 | 
			
		||||
    data->count++;
 | 
			
		||||
    EekBounds key_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(element, &key_bounds);
 | 
			
		||||
    data->total_width += key_bounds.width;
 | 
			
		||||
    if (key_bounds.height > data->biggest_height) {
 | 
			
		||||
        data->biggest_height = key_bounds.height;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
keyplacer(EekElement *element, gpointer user_data)
 | 
			
		||||
{
 | 
			
		||||
    EekKey *key = EEK_KEY(element);
 | 
			
		||||
 | 
			
		||||
    /* Skip keys without labels for the current level. */
 | 
			
		||||
    if (!eek_key_has_label(key))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    double *current_offset = user_data;
 | 
			
		||||
    EekBounds key_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(element, &key_bounds);
 | 
			
		||||
    key_bounds.x = *current_offset;
 | 
			
		||||
    key_bounds.y = 0;
 | 
			
		||||
    eek_element_set_bounds(element, &key_bounds);
 | 
			
		||||
    *current_offset += key_bounds.width + keyspacing;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_section_place_keys(EekSection *section, EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    eek_container_foreach_child(EEK_CONTAINER(section), keysizer, keyboard);
 | 
			
		||||
 | 
			
		||||
    struct keys_info keyinfo = {0};
 | 
			
		||||
    eek_container_foreach_child(EEK_CONTAINER(section), keycounter, &keyinfo);
 | 
			
		||||
    EekBounds section_bounds = {0};
 | 
			
		||||
    eek_element_get_bounds(EEK_ELEMENT(section), §ion_bounds);
 | 
			
		||||
 | 
			
		||||
    double key_offset = (section_bounds.width - (keyinfo.total_width + (keyinfo.count - 1) * keyspacing)) / 2;
 | 
			
		||||
    eek_container_foreach_child(EEK_CONTAINER(section), keyplacer, &key_offset);
 | 
			
		||||
 | 
			
		||||
    section_bounds.height = keyinfo.biggest_height;
 | 
			
		||||
    eek_element_set_bounds(EEK_ELEMENT(section), §ion_bounds);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -25,10 +25,90 @@
 | 
			
		||||
#ifndef EEK_SECTION_H
 | 
			
		||||
#define EEK_SECTION_H 1
 | 
			
		||||
 | 
			
		||||
/* Contains row-related functions that couldn't be done in Rust easily. */
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "src/layout.h"
 | 
			
		||||
#include "eek-container.h"
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_SECTION (eek_section_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE(EekSection, eek_section, EEK, SECTION, EekContainer)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekSectionClass:
 | 
			
		||||
 * @get_n_rows: virtual function for getting the number of rows in the section
 | 
			
		||||
 * @add_row: virtual function for adding a new row to the section
 | 
			
		||||
 * @get_row: virtual function for accessing a row in the section
 | 
			
		||||
 * @create_key: virtual function for creating key in the section
 | 
			
		||||
 * @key_pressed: class handler for #EekSection::key-pressed signal
 | 
			
		||||
 * @key_released: class handler for #EekSection::key-released signal
 | 
			
		||||
 * @key_locked: class handler for #EekSection::key-locked signal
 | 
			
		||||
 * @key_unlocked: class handler for #EekSection::key-unlocked signal
 | 
			
		||||
 * @key_cancelled: class handler for #EekSection::key-cancelled signal
 | 
			
		||||
 */
 | 
			
		||||
struct _EekSectionClass
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekContainerClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    gint    (* get_n_rows)          (EekSection     *self);
 | 
			
		||||
    void    (* add_row)             (EekSection     *self,
 | 
			
		||||
                                     gint            num_columns,
 | 
			
		||||
                                     EekOrientation  orientation);
 | 
			
		||||
    void    (* get_row)             (EekSection     *self,
 | 
			
		||||
                                     gint            index,
 | 
			
		||||
                                     gint           *num_columns,
 | 
			
		||||
                                     EekOrientation *orientation);
 | 
			
		||||
 | 
			
		||||
    EekKey *(* create_key)          (EekSection     *self,
 | 
			
		||||
                                     const gchar    *name,
 | 
			
		||||
                                     gint            keycode,
 | 
			
		||||
                                     gint            row,
 | 
			
		||||
                                     gint            column);
 | 
			
		||||
 | 
			
		||||
    /* signals */
 | 
			
		||||
    void    (* key_pressed)         (EekSection     *self,
 | 
			
		||||
                                     EekKey         *key);
 | 
			
		||||
    void    (* key_released)        (EekSection     *self,
 | 
			
		||||
                                     EekKey         *key);
 | 
			
		||||
    void    (* key_locked)          (EekSection     *self,
 | 
			
		||||
                                     EekKey         *key);
 | 
			
		||||
    void    (* key_unlocked)        (EekSection     *self,
 | 
			
		||||
                                     EekKey         *key);
 | 
			
		||||
    void    (* key_cancelled)       (EekSection     *self,
 | 
			
		||||
                                     EekKey         *key);
 | 
			
		||||
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* padding */
 | 
			
		||||
    gpointer pdummy[19];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType   eek_section_get_type             (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
void    eek_section_set_angle            (EekSection     *section,
 | 
			
		||||
                                          gint            angle);
 | 
			
		||||
gint    eek_section_get_angle            (EekSection     *section);
 | 
			
		||||
 | 
			
		||||
gint    eek_section_get_n_rows           (EekSection     *section);
 | 
			
		||||
void    eek_section_add_row              (EekSection     *section,
 | 
			
		||||
                                          gint            num_columns,
 | 
			
		||||
                                          EekOrientation  orientation);
 | 
			
		||||
void    eek_section_get_row              (EekSection     *section,
 | 
			
		||||
                                          gint            index,
 | 
			
		||||
                                          gint           *num_columns,
 | 
			
		||||
                                          EekOrientation *orientation);
 | 
			
		||||
 | 
			
		||||
EekKey *eek_section_create_key           (EekSection     *section,
 | 
			
		||||
                                          const gchar    *name,
 | 
			
		||||
                                          gint            keycode,
 | 
			
		||||
                                          gint            column,
 | 
			
		||||
                                          gint            row);
 | 
			
		||||
 | 
			
		||||
EekKey *eek_section_find_key_by_keycode  (EekSection     *section,
 | 
			
		||||
                                          guint           keycode);
 | 
			
		||||
 | 
			
		||||
void eek_section_place_keys              (EekSection     *section, EekKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_SECTION_H */
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										91
									
								
								eek/eek-serializable.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								eek/eek-serializable.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,91 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
 | 
			
		||||
 * Copyright (C) 2008-2010 Red Hat, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public
 | 
			
		||||
 * License as published by the Free Software Foundation; either
 | 
			
		||||
 * version 2 of the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This library is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the
 | 
			
		||||
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 | 
			
		||||
 * Boston, MA 02111-1307, USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-serializable
 | 
			
		||||
 * @short_description: Interface which provides object serialization
 | 
			
		||||
 * into #GVariant
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekSerializableIface interface defines serialize/deserialize
 | 
			
		||||
 * method.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-serializable.h"
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
eek_serializable_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
    static GType iface_type = 0;
 | 
			
		||||
    if (iface_type == 0) {
 | 
			
		||||
        static const GTypeInfo info = {
 | 
			
		||||
            sizeof (EekSerializableIface),
 | 
			
		||||
            NULL,
 | 
			
		||||
            NULL,
 | 
			
		||||
        };
 | 
			
		||||
        iface_type = g_type_register_static (G_TYPE_INTERFACE,
 | 
			
		||||
                                             "EekSerializable",
 | 
			
		||||
                                             &info, 0);
 | 
			
		||||
    }
 | 
			
		||||
    return iface_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GVariant *
 | 
			
		||||
eek_serializable_serialize (EekSerializable *object)
 | 
			
		||||
{
 | 
			
		||||
    GVariantBuilder builder;
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SERIALIZABLE (object), FALSE);
 | 
			
		||||
 | 
			
		||||
    g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
 | 
			
		||||
    g_variant_builder_add (&builder, "s", g_type_name (G_OBJECT_TYPE (object)));
 | 
			
		||||
    EEK_SERIALIZABLE_GET_IFACE (object)->serialize (object, &builder);
 | 
			
		||||
 | 
			
		||||
    return g_variant_builder_end (&builder);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekSerializable *
 | 
			
		||||
eek_serializable_deserialize (GVariant *variant)
 | 
			
		||||
{
 | 
			
		||||
    gchar *type_name = NULL;
 | 
			
		||||
    GType type;
 | 
			
		||||
    EekSerializable *object;
 | 
			
		||||
    gsize index = 0;
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (variant != NULL, NULL);
 | 
			
		||||
 | 
			
		||||
    g_variant_get_child (variant, index++, "&s", &type_name);
 | 
			
		||||
    type = g_type_from_name (type_name);
 | 
			
		||||
 | 
			
		||||
    g_return_val_if_fail (g_type_is_a (type, EEK_TYPE_SERIALIZABLE), NULL);
 | 
			
		||||
 | 
			
		||||
    object = g_object_new (type, NULL);
 | 
			
		||||
 | 
			
		||||
    index = EEK_SERIALIZABLE_GET_IFACE (object)->deserialize (object,
 | 
			
		||||
                                                              variant,
 | 
			
		||||
                                                              index);
 | 
			
		||||
    if (index < 0) {
 | 
			
		||||
        g_object_unref (object);
 | 
			
		||||
        g_return_val_if_reached (NULL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return object;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										66
									
								
								eek/eek-serializable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								eek/eek-serializable.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This program is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License
 | 
			
		||||
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEK_SERIALIZABLE_H
 | 
			
		||||
#define EEK_SERIALIZABLE_H 1
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_SERIALIZABLE (eek_serializable_get_type())
 | 
			
		||||
#define EEK_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_SERIALIZABLE, EekSerializable))
 | 
			
		||||
#define EEK_IS_SERIALIZABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_SERIALIZABLE))
 | 
			
		||||
#define EEK_SERIALIZABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), EEK_TYPE_SERIALIZABLE, EekSerializableIface))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekSerializable EekSerializable;
 | 
			
		||||
typedef struct _EekSerializableIface EekSerializableIface;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekSerializableIface:
 | 
			
		||||
 *
 | 
			
		||||
 * @serialize: virtual function for serializing object into #GVariant
 | 
			
		||||
 * @deserialize: virtual function for deserializing object from #GVariant
 | 
			
		||||
 */
 | 
			
		||||
struct _EekSerializableIface
 | 
			
		||||
{
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    GTypeInterface parent_iface;
 | 
			
		||||
 | 
			
		||||
    void  (* serialize)   (EekSerializable       *object,
 | 
			
		||||
                           GVariantBuilder       *builder);
 | 
			
		||||
    gsize (* deserialize) (EekSerializable       *object,
 | 
			
		||||
                           GVariant              *variant,
 | 
			
		||||
                           gsize                  index);
 | 
			
		||||
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* padding */
 | 
			
		||||
    gpointer pdummy[24];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType            eek_serializable_get_type    (void);
 | 
			
		||||
 | 
			
		||||
GVariant        *eek_serializable_serialize   (EekSerializable *object);
 | 
			
		||||
EekSerializable *eek_serializable_deserialize (GVariant        *variant);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_SERIALIZABLE_H */
 | 
			
		||||
							
								
								
									
										105
									
								
								eek/eek-symbol-matrix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								eek/eek-symbol-matrix.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,105 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
#include "eek-symbol-matrix.h"
 | 
			
		||||
 | 
			
		||||
EekSymbolMatrix *
 | 
			
		||||
eek_symbol_matrix_new (gint num_groups,
 | 
			
		||||
                       gint num_levels)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolMatrix *matrix = g_slice_new (EekSymbolMatrix);
 | 
			
		||||
 | 
			
		||||
    matrix->num_groups = num_groups;
 | 
			
		||||
    matrix->num_levels = num_levels;
 | 
			
		||||
    matrix->data = g_slice_alloc0 (sizeof (EekSymbol *) *
 | 
			
		||||
                                   num_groups * num_levels);
 | 
			
		||||
    return matrix;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekSymbolMatrix *
 | 
			
		||||
eek_symbol_matrix_copy (const EekSymbolMatrix *matrix)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolMatrix *retval;
 | 
			
		||||
    gint i, num_symbols = matrix->num_groups * matrix->num_levels;
 | 
			
		||||
 | 
			
		||||
    retval = g_slice_dup (EekSymbolMatrix, matrix);
 | 
			
		||||
    retval->data = g_slice_copy (sizeof (EekSymbol *) * num_symbols,
 | 
			
		||||
                                 matrix->data);
 | 
			
		||||
    for (i = 0; i < num_symbols; i++)
 | 
			
		||||
        if (retval->data[i])
 | 
			
		||||
            g_object_ref (retval->data[i]);
 | 
			
		||||
    return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_matrix_free (EekSymbolMatrix *matrix)
 | 
			
		||||
{
 | 
			
		||||
    gint i, num_symbols = matrix->num_groups * matrix->num_levels;
 | 
			
		||||
    for (i = 0; i < num_symbols; i++)
 | 
			
		||||
        if (matrix->data[i])
 | 
			
		||||
            g_object_unref (matrix->data[i]);
 | 
			
		||||
    g_slice_free1 (sizeof (EekSymbol *) * num_symbols, matrix->data);
 | 
			
		||||
    g_slice_free (EekSymbolMatrix, matrix);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GType
 | 
			
		||||
eek_symbol_matrix_get_type (void)
 | 
			
		||||
{
 | 
			
		||||
    static GType our_type = 0;
 | 
			
		||||
 | 
			
		||||
    if (our_type == 0)
 | 
			
		||||
        our_type =
 | 
			
		||||
            g_boxed_type_register_static ("EekSymbolMatrix",
 | 
			
		||||
                                          (GBoxedCopyFunc)eek_symbol_matrix_copy,
 | 
			
		||||
                                          (GBoxedFreeFunc)eek_symbol_matrix_free);
 | 
			
		||||
    return our_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_matrix_set_symbol (EekSymbolMatrix *matrix,
 | 
			
		||||
                              gint             group,
 | 
			
		||||
                              gint             level,
 | 
			
		||||
                              EekSymbol       *symbol)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (group >= 0 && group < matrix->num_groups);
 | 
			
		||||
    g_return_if_fail (level >= 0 && level < matrix->num_levels);
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
    matrix->data[group * matrix->num_levels + level] = g_object_ref (symbol);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_matrix_get_symbol:
 | 
			
		||||
 * @matrix: an #EekSymbolMatrix
 | 
			
		||||
 * @group: group index of @matrix
 | 
			
		||||
 * @level: level index of @matrix
 | 
			
		||||
 *
 | 
			
		||||
 * Get an #EekSymbol stored in the cell selected by (@group, @level)
 | 
			
		||||
 * in @matrix.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): an #EekSymbol.
 | 
			
		||||
 */
 | 
			
		||||
EekSymbol *
 | 
			
		||||
eek_symbol_matrix_get_symbol (EekSymbolMatrix *matrix,
 | 
			
		||||
                              gint             group,
 | 
			
		||||
                              gint             level)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (group >= 0 && group < matrix->num_groups, NULL);
 | 
			
		||||
    g_return_val_if_fail (level >= 0 && level < matrix->num_levels, NULL);
 | 
			
		||||
    return matrix->data[group * matrix->num_levels + level];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										62
									
								
								eek/eek-symbol-matrix.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								eek/eek-symbol-matrix.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef EEK_SYMBOL_MATRIX_H
 | 
			
		||||
#define EEK_SYMBOL_MATRIX_H 1
 | 
			
		||||
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekSymbolMatrix:
 | 
			
		||||
 * @data: array of symbols
 | 
			
		||||
 * @num_groups: the number of groups (rows)
 | 
			
		||||
 * @num_levels: the number of levels (columns)
 | 
			
		||||
 *
 | 
			
		||||
 * Symbol matrix of a key.
 | 
			
		||||
 */
 | 
			
		||||
struct _EekSymbolMatrix
 | 
			
		||||
{
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    gint num_groups;
 | 
			
		||||
    gint num_levels;
 | 
			
		||||
    EekSymbol **data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_SYMBOL_MATRIX (eek_symbol_matrix_get_type ())
 | 
			
		||||
GType            eek_symbol_matrix_get_type (void) G_GNUC_CONST;
 | 
			
		||||
EekSymbolMatrix *eek_symbol_matrix_new      (gint                   num_groups,
 | 
			
		||||
                                             gint                   num_levels);
 | 
			
		||||
EekSymbolMatrix *eek_symbol_matrix_copy     (const EekSymbolMatrix *matrix);
 | 
			
		||||
void             eek_symbol_matrix_free     (EekSymbolMatrix       *matrix);
 | 
			
		||||
 | 
			
		||||
void             eek_symbol_matrix_set_symbol
 | 
			
		||||
                                            (EekSymbolMatrix       *matrix,
 | 
			
		||||
                                             gint                   group,
 | 
			
		||||
                                             gint                   level,
 | 
			
		||||
                                             EekSymbol             *symbol);
 | 
			
		||||
EekSymbol       *eek_symbol_matrix_get_symbol
 | 
			
		||||
                                            (EekSymbolMatrix       *matrix,
 | 
			
		||||
                                             gint                   group,
 | 
			
		||||
                                             gint                   level);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif  /* EEK_SYMBOL_MATRIX_H */
 | 
			
		||||
							
								
								
									
										443
									
								
								eek/eek-symbol.c
									
									
									
									
									
								
							
							
						
						
									
										443
									
								
								eek/eek-symbol.c
									
									
									
									
									
								
							@ -28,15 +28,270 @@
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
#include "eek-serializable.h"
 | 
			
		||||
#include "eek-enumtypes.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_NAME,
 | 
			
		||||
    PROP_LABEL,
 | 
			
		||||
    PROP_CATEGORY,
 | 
			
		||||
    PROP_MODIFIER_MASK,
 | 
			
		||||
    PROP_ICON_NAME,
 | 
			
		||||
    PROP_TOOLTIP,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _EekSymbolPrivate
 | 
			
		||||
{
 | 
			
		||||
    gchar *name;
 | 
			
		||||
    gchar *label;
 | 
			
		||||
    EekSymbolCategory category;
 | 
			
		||||
    EekModifierType modifier_mask;
 | 
			
		||||
    gchar *icon_name;
 | 
			
		||||
    gchar *tooltip;
 | 
			
		||||
} EekSymbolPrivate;
 | 
			
		||||
 | 
			
		||||
static void eek_serializable_iface_init (EekSerializableIface *iface);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_EXTENDED (EekSymbol,
 | 
			
		||||
			eek_symbol,
 | 
			
		||||
			G_TYPE_OBJECT,
 | 
			
		||||
			0, /* GTypeFlags */
 | 
			
		||||
			G_ADD_PRIVATE (EekSymbol)
 | 
			
		||||
                        G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
 | 
			
		||||
                                               eek_serializable_iface_init))
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_real_serialize (EekSerializable *self,
 | 
			
		||||
                           GVariantBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
 | 
			
		||||
#define NOTNULL(s) ((s) != NULL ? (s) : "")
 | 
			
		||||
    g_variant_builder_add (builder, "s", NOTNULL(priv->name));
 | 
			
		||||
    g_variant_builder_add (builder, "s", NOTNULL(priv->label));
 | 
			
		||||
    g_variant_builder_add (builder, "u", priv->category);
 | 
			
		||||
    g_variant_builder_add (builder, "u", priv->modifier_mask);
 | 
			
		||||
    g_variant_builder_add (builder, "s", NOTNULL(priv->icon_name));
 | 
			
		||||
    g_variant_builder_add (builder, "s", NOTNULL(priv->tooltip));
 | 
			
		||||
#undef NOTNULL
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gsize
 | 
			
		||||
eek_symbol_real_deserialize (EekSerializable *self,
 | 
			
		||||
                             GVariant        *variant,
 | 
			
		||||
                             gsize            index)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (EEK_SYMBOL (self));
 | 
			
		||||
 | 
			
		||||
    g_variant_get_child (variant, index++, "s", &priv->name);
 | 
			
		||||
    g_variant_get_child (variant, index++, "s", &priv->label);
 | 
			
		||||
    g_variant_get_child (variant, index++, "u", &priv->category);
 | 
			
		||||
    g_variant_get_child (variant, index++, "u", &priv->modifier_mask);
 | 
			
		||||
    g_variant_get_child (variant, index++, "s", &priv->icon_name);
 | 
			
		||||
    g_variant_get_child (variant, index++, "s", &priv->tooltip);
 | 
			
		||||
 | 
			
		||||
    return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_serializable_iface_init (EekSerializableIface *iface)
 | 
			
		||||
{
 | 
			
		||||
    iface->serialize = eek_symbol_real_serialize;
 | 
			
		||||
    iface->deserialize = eek_symbol_real_deserialize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_set_property (GObject      *object,
 | 
			
		||||
                         guint         prop_id,
 | 
			
		||||
                         const GValue *value,
 | 
			
		||||
                         GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_NAME:
 | 
			
		||||
        eek_symbol_set_name (EEK_SYMBOL(object), g_value_get_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_LABEL:
 | 
			
		||||
        eek_symbol_set_label (EEK_SYMBOL(object), g_value_get_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_CATEGORY:
 | 
			
		||||
        eek_symbol_set_category (EEK_SYMBOL(object), g_value_get_enum (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_MODIFIER_MASK:
 | 
			
		||||
        eek_symbol_set_modifier_mask (EEK_SYMBOL(object),
 | 
			
		||||
                                      g_value_get_flags (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_ICON_NAME:
 | 
			
		||||
        eek_symbol_set_icon_name (EEK_SYMBOL(object),
 | 
			
		||||
                                  g_value_get_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_TOOLTIP:
 | 
			
		||||
        eek_symbol_set_tooltip (EEK_SYMBOL(object),
 | 
			
		||||
                                g_value_get_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_get_property (GObject    *object,
 | 
			
		||||
                         guint       prop_id,
 | 
			
		||||
                         GValue     *value,
 | 
			
		||||
                         GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_NAME:
 | 
			
		||||
        g_value_set_string (value, eek_symbol_get_name (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_LABEL:
 | 
			
		||||
        g_value_set_string (value, eek_symbol_get_label (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_CATEGORY:
 | 
			
		||||
        g_value_set_enum (value, eek_symbol_get_category (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_MODIFIER_MASK:
 | 
			
		||||
        g_value_set_flags (value,
 | 
			
		||||
                           eek_symbol_get_modifier_mask (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_ICON_NAME:
 | 
			
		||||
        g_value_set_string (value,
 | 
			
		||||
                            eek_symbol_get_icon_name (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    case PROP_TOOLTIP:
 | 
			
		||||
        g_value_set_string (value,
 | 
			
		||||
                            eek_symbol_get_tooltip (EEK_SYMBOL(object)));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbol        *self = EEK_SYMBOL (object);
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->name);
 | 
			
		||||
    g_free (priv->label);
 | 
			
		||||
    g_free (priv->icon_name);
 | 
			
		||||
    g_free (priv->tooltip);
 | 
			
		||||
    G_OBJECT_CLASS (eek_symbol_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_class_init (EekSymbolClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_symbol_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_symbol_get_property;
 | 
			
		||||
    gobject_class->finalize = eek_symbol_finalize;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("name",
 | 
			
		||||
                                 "Name",
 | 
			
		||||
                                 "Canonical name of the symbol",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_NAME, pspec);
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("label",
 | 
			
		||||
                                 "Label",
 | 
			
		||||
                                 "Text used to display the symbol",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_LABEL, pspec);
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_enum ("category",
 | 
			
		||||
                               "Category",
 | 
			
		||||
                               "Category of the symbol",
 | 
			
		||||
                               EEK_TYPE_SYMBOL_CATEGORY,
 | 
			
		||||
                               EEK_SYMBOL_CATEGORY_UNKNOWN,
 | 
			
		||||
                               G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_CATEGORY, pspec);
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_flags ("modifier-mask",
 | 
			
		||||
                                "Modifier mask",
 | 
			
		||||
                                "Modifier mask of the symbol",
 | 
			
		||||
                                EEK_TYPE_MODIFIER_TYPE,
 | 
			
		||||
                                0,
 | 
			
		||||
                                G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_MODIFIER_MASK, pspec);
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("icon-name",
 | 
			
		||||
                                 "Icon name",
 | 
			
		||||
                                 "Icon name used to render the symbol",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_ICON_NAME, pspec);
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("tooltip",
 | 
			
		||||
                                 "Tooltip",
 | 
			
		||||
                                 "Tooltip text",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_TOOLTIP, pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_symbol_init (EekSymbol *self)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    priv->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_new:
 | 
			
		||||
 * @name: name of the symbol
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new #EekSymbol with @name.
 | 
			
		||||
 */
 | 
			
		||||
EekSymbol *
 | 
			
		||||
eek_symbol_new (const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    EekSymbol *self = g_new0(EekSymbol, 1);
 | 
			
		||||
    self->name = g_strdup (name);
 | 
			
		||||
    self->category = EEK_SYMBOL_CATEGORY_UNKNOWN;
 | 
			
		||||
    return self;
 | 
			
		||||
    return g_object_new (EEK_TYPE_SYMBOL, "name", name, NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_set_name:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 * @name: name of the symbol
 | 
			
		||||
 *
 | 
			
		||||
 * Set the name of @symbol to @name.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_set_name (EekSymbol   *symbol,
 | 
			
		||||
                     const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->name);
 | 
			
		||||
    priv->name = g_strdup (name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_get_name:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Get the name of @symbol.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_symbol_get_name (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    if (priv->name == NULL || *priv->name == '\0')
 | 
			
		||||
        return NULL;
 | 
			
		||||
    return priv->name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -50,8 +305,64 @@ void
 | 
			
		||||
eek_symbol_set_label (EekSymbol   *symbol,
 | 
			
		||||
                      const gchar *label)
 | 
			
		||||
{
 | 
			
		||||
    g_free (symbol->label);
 | 
			
		||||
    symbol->label = g_strdup (label);
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->label);
 | 
			
		||||
    priv->label = g_strdup (label);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_get_label:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Get the label text of @symbol.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_symbol_get_label (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    if (priv->label == NULL || *priv->label == '\0')
 | 
			
		||||
        return NULL;
 | 
			
		||||
    return priv->label;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_set_category:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 * @category: an #EekSymbolCategory
 | 
			
		||||
 *
 | 
			
		||||
 * Set symbol category of @symbol to @category.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_set_category (EekSymbol        *symbol,
 | 
			
		||||
                         EekSymbolCategory category)
 | 
			
		||||
{
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    priv->category = category;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_get_category:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Get symbol category of @symbol.
 | 
			
		||||
 */
 | 
			
		||||
EekSymbolCategory
 | 
			
		||||
eek_symbol_get_category (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), EEK_SYMBOL_CATEGORY_UNKNOWN);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    return priv->category;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -65,7 +376,11 @@ void
 | 
			
		||||
eek_symbol_set_modifier_mask (EekSymbol      *symbol,
 | 
			
		||||
                              EekModifierType mask)
 | 
			
		||||
{
 | 
			
		||||
    symbol->modifier_mask = mask;
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    priv->modifier_mask = mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -77,37 +392,131 @@ eek_symbol_set_modifier_mask (EekSymbol      *symbol,
 | 
			
		||||
EekModifierType
 | 
			
		||||
eek_symbol_get_modifier_mask (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    return 0;
 | 
			
		||||
    return symbol->modifier_mask;
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), 0);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    return priv->modifier_mask;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_is_modifier:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Check if @symbol is a modifier.
 | 
			
		||||
 * Returns: %TRUE if @symbol is a modifier.
 | 
			
		||||
 */
 | 
			
		||||
gboolean
 | 
			
		||||
eek_symbol_is_modifier (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    return eek_symbol_get_modifier_mask (symbol) != 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_set_icon_name:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 * @icon_name: icon name of @symbol
 | 
			
		||||
 *
 | 
			
		||||
 * Set the icon name of @symbol to @icon_name.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_set_icon_name (EekSymbol   *symbol,
 | 
			
		||||
                          const gchar *icon_name)
 | 
			
		||||
{
 | 
			
		||||
    g_free (symbol->icon_name);
 | 
			
		||||
    symbol->icon_name = g_strdup (icon_name);
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->icon_name);
 | 
			
		||||
    priv->icon_name = g_strdup (icon_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_get_icon_name:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Get the icon name of @symbol.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_symbol_get_icon_name (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    if (priv->icon_name == NULL || *priv->icon_name == '\0')
 | 
			
		||||
        return NULL;
 | 
			
		||||
    return priv->icon_name;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_set_tooltip:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 * @tooltip: icon name of @symbol
 | 
			
		||||
 *
 | 
			
		||||
 * Set the tooltip text of @symbol to @tooltip.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_symbol_set_tooltip (EekSymbol   *symbol,
 | 
			
		||||
                        const gchar *tooltip)
 | 
			
		||||
{
 | 
			
		||||
    g_free (symbol->tooltip);
 | 
			
		||||
    symbol->tooltip = g_strdup (tooltip);
 | 
			
		||||
    g_return_if_fail (EEK_IS_SYMBOL(symbol));
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->tooltip);
 | 
			
		||||
    priv->tooltip = g_strdup (tooltip);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_symbol_get_tooltip:
 | 
			
		||||
 * @symbol: an #EekSymbol
 | 
			
		||||
 *
 | 
			
		||||
 * Get the tooltip text of @symbol.
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_symbol_get_tooltip (EekSymbol *symbol)
 | 
			
		||||
{
 | 
			
		||||
    return NULL;
 | 
			
		||||
    if (symbol->tooltip == NULL || *symbol->tooltip == '\0')
 | 
			
		||||
    g_return_val_if_fail (EEK_IS_SYMBOL(symbol), NULL);
 | 
			
		||||
 | 
			
		||||
    EekSymbolPrivate *priv = eek_symbol_get_instance_private (symbol);
 | 
			
		||||
 | 
			
		||||
    if (priv->tooltip == NULL || *priv->tooltip == '\0')
 | 
			
		||||
        return NULL;
 | 
			
		||||
    return symbol->tooltip;
 | 
			
		||||
    return priv->tooltip;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct {
 | 
			
		||||
    EekSymbolCategory category;
 | 
			
		||||
    gchar *name;
 | 
			
		||||
} category_names[] = {
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_LETTER, "letter" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_FUNCTION, "function" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_KEYNAME, "keyname" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_USER0, "user0" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_USER1, "user1" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_USER2, "user2" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_USER3, "user3" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_USER4, "user4" },
 | 
			
		||||
    { EEK_SYMBOL_CATEGORY_UNKNOWN, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_symbol_category_get_name (EekSymbolCategory category)
 | 
			
		||||
{
 | 
			
		||||
    gint i;
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(category_names); i++)
 | 
			
		||||
        if (category_names[i].category == category)
 | 
			
		||||
            return category_names[i].name;
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekSymbolCategory
 | 
			
		||||
eek_symbol_category_from_name (const gchar *name)
 | 
			
		||||
{
 | 
			
		||||
    gint i;
 | 
			
		||||
    for (i = 0; i < G_N_ELEMENTS(category_names); i++)
 | 
			
		||||
        if (g_strcmp0 (category_names[i].name, name) == 0)
 | 
			
		||||
            return category_names[i].category;
 | 
			
		||||
    return EEK_SYMBOL_CATEGORY_UNKNOWN;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								eek/eek-symbol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								eek/eek-symbol.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,100 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEK_SYMBOL_H
 | 
			
		||||
#define EEK_SYMBOL_H 1
 | 
			
		||||
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekSymbolCategory:
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_LETTER: the symbol represents an alphabet letter
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_FUNCTION: the symbol represents a function
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_KEYNAME: the symbol does not have meaning but
 | 
			
		||||
 * have a name
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_USER0: reserved for future use
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_USER1: reserved for future use
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_USER2: reserved for future use
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_USER3: reserved for future use
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_USER4: reserved for future use
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_UNKNOWN: used for error reporting
 | 
			
		||||
 * @EEK_SYMBOL_CATEGORY_LAST: the last symbol category
 | 
			
		||||
 *
 | 
			
		||||
 * Category of the key symbols.
 | 
			
		||||
 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_LETTER,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_FUNCTION,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_KEYNAME,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_USER0,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_USER1,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_USER2,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_USER3,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_USER4,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_UNKNOWN,
 | 
			
		||||
    EEK_SYMBOL_CATEGORY_LAST = EEK_SYMBOL_CATEGORY_UNKNOWN
 | 
			
		||||
} EekSymbolCategory;
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_SYMBOL (eek_symbol_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE(EekSymbol, eek_symbol, EEK, SYMBOL, GObject)
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekSymbolClass:
 | 
			
		||||
 */
 | 
			
		||||
struct _EekSymbolClass {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType             eek_symbol_get_type           (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
EekSymbol        *eek_symbol_new                (const gchar      *name);
 | 
			
		||||
void              eek_symbol_set_name           (EekSymbol        *symbol,
 | 
			
		||||
                                                 const gchar      *name);
 | 
			
		||||
const gchar      *eek_symbol_get_name           (EekSymbol        *symbol);
 | 
			
		||||
void              eek_symbol_set_label          (EekSymbol        *symbol,
 | 
			
		||||
                                                 const gchar      *label);
 | 
			
		||||
const gchar      *eek_symbol_get_label          (EekSymbol        *symbol);
 | 
			
		||||
void              eek_symbol_set_category       (EekSymbol        *symbol,
 | 
			
		||||
                                                 EekSymbolCategory category);
 | 
			
		||||
EekSymbolCategory eek_symbol_get_category       (EekSymbol        *symbol);
 | 
			
		||||
EekModifierType   eek_symbol_get_modifier_mask  (EekSymbol        *symbol);
 | 
			
		||||
void              eek_symbol_set_modifier_mask  (EekSymbol        *symbol,
 | 
			
		||||
                                                 EekModifierType   mask);
 | 
			
		||||
gboolean          eek_symbol_is_modifier        (EekSymbol        *symbol);
 | 
			
		||||
void              eek_symbol_set_icon_name      (EekSymbol        *symbol,
 | 
			
		||||
                                                 const gchar      *icon_name);
 | 
			
		||||
const gchar      *eek_symbol_get_icon_name      (EekSymbol        *symbol);
 | 
			
		||||
void              eek_symbol_set_tooltip        (EekSymbol        *symbol,
 | 
			
		||||
                                                 const gchar      *tooltip);
 | 
			
		||||
const gchar *     eek_symbol_get_tooltip        (EekSymbol        *symbol);
 | 
			
		||||
 | 
			
		||||
const gchar      *eek_symbol_category_get_name  (EekSymbolCategory category);
 | 
			
		||||
EekSymbolCategory eek_symbol_category_from_name (const gchar      *name);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif  /* EEK_SYMBOL_H */
 | 
			
		||||
							
								
								
									
										185
									
								
								eek/eek-text.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								eek/eek-text.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,185 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-text
 | 
			
		||||
 * @short_description: an #EekText represents a text symbol
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-text.h"
 | 
			
		||||
#include "eek-serializable.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_TEXT,
 | 
			
		||||
    PROP_LAST
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct _EekTextPrivate
 | 
			
		||||
{
 | 
			
		||||
    gchar *text;
 | 
			
		||||
} EekTextPrivate;
 | 
			
		||||
 | 
			
		||||
static void eek_serializable_iface_init (EekSerializableIface *iface);
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_EXTENDED (EekText,
 | 
			
		||||
			eek_text,
 | 
			
		||||
			EEK_TYPE_SYMBOL,
 | 
			
		||||
			0, /* GTypeFlags */
 | 
			
		||||
			G_ADD_PRIVATE (EekText)
 | 
			
		||||
                        G_IMPLEMENT_INTERFACE (EEK_TYPE_SERIALIZABLE,
 | 
			
		||||
                                               eek_serializable_iface_init))
 | 
			
		||||
 | 
			
		||||
static EekSerializableIface *eek_text_parent_serializable_iface;
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_real_serialize (EekSerializable *self,
 | 
			
		||||
                         GVariantBuilder *builder)
 | 
			
		||||
{
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
 | 
			
		||||
 | 
			
		||||
    eek_text_parent_serializable_iface->serialize (self, builder);
 | 
			
		||||
 | 
			
		||||
    g_variant_builder_add (builder, "s", priv->text);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gsize
 | 
			
		||||
eek_text_real_deserialize (EekSerializable *self,
 | 
			
		||||
                           GVariant        *variant,
 | 
			
		||||
                           gsize            index)
 | 
			
		||||
{
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (EEK_TEXT (self));
 | 
			
		||||
 | 
			
		||||
    index = eek_text_parent_serializable_iface->deserialize (self,
 | 
			
		||||
                                                             variant,
 | 
			
		||||
                                                             index);
 | 
			
		||||
    g_variant_get_child (variant, index++, "s", &priv->text);
 | 
			
		||||
 | 
			
		||||
    return index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_serializable_iface_init (EekSerializableIface *iface)
 | 
			
		||||
{
 | 
			
		||||
    eek_text_parent_serializable_iface =
 | 
			
		||||
        g_type_interface_peek_parent (iface);
 | 
			
		||||
 | 
			
		||||
    iface->serialize = eek_text_real_serialize;
 | 
			
		||||
    iface->deserialize = eek_text_real_deserialize;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_set_property (GObject      *object,
 | 
			
		||||
                       guint         prop_id,
 | 
			
		||||
                       const GValue *value,
 | 
			
		||||
                       GParamSpec   *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekText        *self = EEK_TEXT (object);
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_TEXT:
 | 
			
		||||
        g_free (priv->text);
 | 
			
		||||
        priv->text = g_strdup (g_value_get_string (value));
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_get_property (GObject    *object,
 | 
			
		||||
                       guint       prop_id,
 | 
			
		||||
                       GValue     *value,
 | 
			
		||||
                       GParamSpec *pspec)
 | 
			
		||||
{
 | 
			
		||||
    EekText        *self = EEK_TEXT (object);
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    switch (prop_id) {
 | 
			
		||||
    case PROP_TEXT:
 | 
			
		||||
        g_value_set_string (value, priv->text);
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekText        *self = EEK_TEXT (object);
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (self);
 | 
			
		||||
 | 
			
		||||
    g_free (priv->text);
 | 
			
		||||
    G_OBJECT_CLASS (eek_text_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_class_init (EekTextClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_text_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_text_get_property;
 | 
			
		||||
    gobject_class->finalize = eek_text_finalize;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("text",
 | 
			
		||||
                                 "Text",
 | 
			
		||||
                                 "Text",
 | 
			
		||||
                                 NULL,
 | 
			
		||||
                                 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_TEXT, pspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_text_init (EekText *self)
 | 
			
		||||
{
 | 
			
		||||
    /* void */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
EekText *
 | 
			
		||||
eek_text_new (const gchar *text)
 | 
			
		||||
{
 | 
			
		||||
    return g_object_new (EEK_TYPE_TEXT,
 | 
			
		||||
                         "label", text,
 | 
			
		||||
                         "category", EEK_SYMBOL_CATEGORY_FUNCTION,
 | 
			
		||||
                         "text", text,
 | 
			
		||||
                         NULL);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_text_get_text:
 | 
			
		||||
 * @text: an #EekText
 | 
			
		||||
 *
 | 
			
		||||
 * Get a text value associated with @text
 | 
			
		||||
 */
 | 
			
		||||
const gchar *
 | 
			
		||||
eek_text_get_text (EekText *text)
 | 
			
		||||
{
 | 
			
		||||
    EekTextPrivate *priv = eek_text_get_instance_private (text);
 | 
			
		||||
 | 
			
		||||
    return priv->text;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								eek/eek-text.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								eek/eek-text.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef EEK_TEXT_H
 | 
			
		||||
#define EEK_TEXT_H 1
 | 
			
		||||
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_TEXT (eek_text_get_type())
 | 
			
		||||
G_DECLARE_DERIVABLE_TYPE(EekText, eek_text, EEK, TEXT, EekSymbol)
 | 
			
		||||
 | 
			
		||||
struct _EekTextClass {
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    EekSymbolClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
GType        eek_text_get_type (void) G_GNUC_CONST;
 | 
			
		||||
EekText     *eek_text_new      (const gchar *text);
 | 
			
		||||
const gchar *eek_text_get_text (EekText     *text);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif  /* EEK_TEXT_H */
 | 
			
		||||
							
								
								
									
										287
									
								
								eek/eek-theme-context.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										287
									
								
								eek/eek-theme-context.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,287 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * eek-theme-context.c: holds global information about a tree of styled objects
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2009, 2010 Red Hat, Inc.
 | 
			
		||||
 * Copyright 2009 Florian Müllner
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as
 | 
			
		||||
 * published by the Free Software Foundation, either version 2.1 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT ANY
 | 
			
		||||
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "config.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-theme.h"
 | 
			
		||||
#include "eek-theme-context.h"
 | 
			
		||||
 | 
			
		||||
struct _EekThemeContext {
 | 
			
		||||
  GObject parent;
 | 
			
		||||
 | 
			
		||||
  double resolution;
 | 
			
		||||
  PangoFontDescription *font;
 | 
			
		||||
  EekThemeNode *root_node;
 | 
			
		||||
  EekTheme *theme;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct _EekThemeContextClass {
 | 
			
		||||
  GObjectClass parent_class;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_RESOLUTION 96.
 | 
			
		||||
#define DEFAULT_FONT "sans-serif 10"
 | 
			
		||||
 | 
			
		||||
enum
 | 
			
		||||
{
 | 
			
		||||
  CHANGED,
 | 
			
		||||
 | 
			
		||||
  LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static guint signals[LAST_SIGNAL] = { 0, };
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE (EekThemeContext, eek_theme_context, G_TYPE_OBJECT)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_theme_context_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
  EekThemeContext *context = EEK_THEME_CONTEXT (object);
 | 
			
		||||
 | 
			
		||||
  if (context->root_node)
 | 
			
		||||
    g_object_unref (context->root_node);
 | 
			
		||||
  if (context->theme)
 | 
			
		||||
    g_object_unref (context->theme);
 | 
			
		||||
 | 
			
		||||
  pango_font_description_free (context->font);
 | 
			
		||||
 | 
			
		||||
  G_OBJECT_CLASS (eek_theme_context_parent_class)->finalize (object);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_theme_context_class_init (EekThemeContextClass *klass)
 | 
			
		||||
{
 | 
			
		||||
  GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
 | 
			
		||||
  object_class->finalize = eek_theme_context_finalize;
 | 
			
		||||
 | 
			
		||||
  signals[CHANGED] =
 | 
			
		||||
    g_signal_new ("changed",
 | 
			
		||||
                  G_TYPE_FROM_CLASS (klass),
 | 
			
		||||
                  G_SIGNAL_RUN_LAST,
 | 
			
		||||
                  0, /* no default handler slot */
 | 
			
		||||
                  NULL, NULL,
 | 
			
		||||
                  g_cclosure_marshal_VOID__VOID,
 | 
			
		||||
                  G_TYPE_NONE, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_theme_context_init (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  context->resolution = DEFAULT_RESOLUTION;
 | 
			
		||||
  context->font = pango_font_description_from_string (DEFAULT_FONT);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_new:
 | 
			
		||||
 *
 | 
			
		||||
 * Create a new theme context.
 | 
			
		||||
 */
 | 
			
		||||
EekThemeContext *
 | 
			
		||||
eek_theme_context_new (void)
 | 
			
		||||
{
 | 
			
		||||
  EekThemeContext *context;
 | 
			
		||||
 | 
			
		||||
  context = g_object_new (EEK_TYPE_THEME_CONTEXT, NULL);
 | 
			
		||||
 | 
			
		||||
  return context;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eek_theme_context_changed (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  EekThemeNode *old_root = context->root_node;
 | 
			
		||||
  context->root_node = NULL;
 | 
			
		||||
 | 
			
		||||
  g_signal_emit (context, signals[CHANGED], 0);
 | 
			
		||||
 | 
			
		||||
  if (old_root)
 | 
			
		||||
    g_object_unref (old_root);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_set_theme:
 | 
			
		||||
 * @context: an #EekThemeContext
 | 
			
		||||
 * @theme: an #EekTheme
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the default set of theme stylesheets for the context. This theme will
 | 
			
		||||
 * be used for the root node and for nodes descending from it, unless some other
 | 
			
		||||
 * style is explicitely specified.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_theme_context_set_theme (EekThemeContext          *context,
 | 
			
		||||
                            EekTheme                 *theme)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
 | 
			
		||||
  g_return_if_fail (theme == NULL || EEK_IS_THEME (theme));
 | 
			
		||||
 | 
			
		||||
  if (context->theme != theme)
 | 
			
		||||
    {
 | 
			
		||||
      if (context->theme)
 | 
			
		||||
        g_object_unref (context->theme);
 | 
			
		||||
 | 
			
		||||
      context->theme = theme;
 | 
			
		||||
 | 
			
		||||
      if (context->theme)
 | 
			
		||||
        g_object_ref (context->theme);
 | 
			
		||||
 | 
			
		||||
      eek_theme_context_changed (context);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_get_theme:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the default theme for the context. See eek_theme_context_set_theme()
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): the default theme for the context
 | 
			
		||||
 */
 | 
			
		||||
EekTheme *
 | 
			
		||||
eek_theme_context_get_theme (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
 | 
			
		||||
 | 
			
		||||
  return context->theme;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_set_resolution:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 * @resolution: resolution of the context (number of pixels in an "inch")
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the resolution of the theme context. This is the scale factor
 | 
			
		||||
 * used to convert between points and the length units pt, in, and cm.
 | 
			
		||||
 * This does not necessarily need to correspond to the actual number
 | 
			
		||||
 * resolution of the device. A value of 72. means that points and
 | 
			
		||||
 * pixels are identical. The default value is 96.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_theme_context_set_resolution (EekThemeContext *context,
 | 
			
		||||
                                 double          resolution)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
 | 
			
		||||
 | 
			
		||||
  if (resolution == context->resolution)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  context->resolution = resolution;
 | 
			
		||||
  eek_theme_context_changed (context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_set_default_resolution:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the resolution of the theme context to the default value of 96.
 | 
			
		||||
 * See eek_theme_context_set_resolution().
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_theme_context_set_default_resolution (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
 | 
			
		||||
 | 
			
		||||
  if (context->resolution == DEFAULT_RESOLUTION)
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  context->resolution = DEFAULT_RESOLUTION;
 | 
			
		||||
  eek_theme_context_changed (context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_get_resolution:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the current resolution of the theme context.
 | 
			
		||||
 * See eek_theme_context_set_resolution().
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the resolution (in dots-per-"inch")
 | 
			
		||||
 */
 | 
			
		||||
double
 | 
			
		||||
eek_theme_context_get_resolution (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), DEFAULT_RESOLUTION);
 | 
			
		||||
 | 
			
		||||
  return context->resolution;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_set_font:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 * @font: the default font for theme context
 | 
			
		||||
 *
 | 
			
		||||
 * Sets the default font for the theme context. This is the font that
 | 
			
		||||
 * is inherited by the root node of the tree of theme nodes. If the
 | 
			
		||||
 * font is not overriden, then this font will be used. If the font is
 | 
			
		||||
 * partially modified (for example, with 'font-size: 110%', then that
 | 
			
		||||
 * modification is based on this font.
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
eek_theme_context_set_font (EekThemeContext             *context,
 | 
			
		||||
                           const PangoFontDescription *font)
 | 
			
		||||
{
 | 
			
		||||
  g_return_if_fail (EEK_IS_THEME_CONTEXT (context));
 | 
			
		||||
  g_return_if_fail (font != NULL);
 | 
			
		||||
 | 
			
		||||
  if (context->font == font ||
 | 
			
		||||
      pango_font_description_equal (context->font, font))
 | 
			
		||||
    return;
 | 
			
		||||
 | 
			
		||||
  pango_font_description_free (context->font);
 | 
			
		||||
  context->font = pango_font_description_copy (font);
 | 
			
		||||
  eek_theme_context_changed (context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_get_font:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the default font for the theme context. See eek_theme_context_set_font().
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: the default font for the theme context.
 | 
			
		||||
 */
 | 
			
		||||
const PangoFontDescription *
 | 
			
		||||
eek_theme_context_get_font (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  g_return_val_if_fail (EEK_IS_THEME_CONTEXT (context), NULL);
 | 
			
		||||
 | 
			
		||||
  return context->font;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_theme_context_get_root_node:
 | 
			
		||||
 * @context: a #EekThemeContext
 | 
			
		||||
 *
 | 
			
		||||
 * Gets the root node of the tree of theme style nodes that associated with this
 | 
			
		||||
 * context. For the node tree associated with a stage, this node represents
 | 
			
		||||
 * styles applied to the stage itself.
 | 
			
		||||
 *
 | 
			
		||||
 * Return value: (transfer none): the root node of the context's style tree
 | 
			
		||||
 */
 | 
			
		||||
EekThemeNode *
 | 
			
		||||
eek_theme_context_get_root_node (EekThemeContext *context)
 | 
			
		||||
{
 | 
			
		||||
  if (context->root_node == NULL)
 | 
			
		||||
    context->root_node = eek_theme_node_new (context, NULL, context->theme,
 | 
			
		||||
                                             G_TYPE_NONE, NULL, NULL, NULL, NULL);
 | 
			
		||||
 | 
			
		||||
  return context->root_node;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										78
									
								
								eek/eek-theme-context.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								eek/eek-theme-context.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,78 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
/*
 | 
			
		||||
 * eek-theme-context.c: holds global information about a tree of styled objects
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 2009, 2010 Red Hat, Inc.
 | 
			
		||||
 * Copyright 2009 Florian Müllner
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as
 | 
			
		||||
 * published by the Free Software Foundation, either version 2.1 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope it will be useful, but WITHOUT ANY
 | 
			
		||||
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
 | 
			
		||||
 * more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef __EEK_THEME_CONTEXT_H__
 | 
			
		||||
#define __EEK_THEME_CONTEXT_H__
 | 
			
		||||
 | 
			
		||||
#include <pango/pango.h>
 | 
			
		||||
#include "eek-theme-node.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-theme-context
 | 
			
		||||
 * @short_description: holds global information about a tree of styled objects
 | 
			
		||||
 *
 | 
			
		||||
 * #EekThemeContext is responsible for managing information global to
 | 
			
		||||
 * a tree of styled objects, such as the set of stylesheets or the
 | 
			
		||||
 * default font.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct _EekThemeContextClass EekThemeContextClass;
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_THEME_CONTEXT             (eek_theme_context_get_type ())
 | 
			
		||||
#define EEK_THEME_CONTEXT(object)          (G_TYPE_CHECK_INSTANCE_CAST ((object), EEK_TYPE_THEME_CONTEXT, EekThemeContext))
 | 
			
		||||
#define EEK_THEME_CONTEXT_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
 | 
			
		||||
#define EEK_IS_THEME_CONTEXT(object)       (G_TYPE_CHECK_INSTANCE_TYPE ((object), EEK_TYPE_THEME_CONTEXT))
 | 
			
		||||
#define EEK_IS_THEME_CONTEXT_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_CONTEXT))
 | 
			
		||||
#define EEK_THEME_CONTEXT_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_CONTEXT, EekThemeContextClass))
 | 
			
		||||
 | 
			
		||||
GType                       eek_theme_context_get_type
 | 
			
		||||
                            (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
EekThemeContext            *eek_theme_context_new
 | 
			
		||||
                            (void);
 | 
			
		||||
 | 
			
		||||
void                        eek_theme_context_set_theme
 | 
			
		||||
                            (EekThemeContext            *context,
 | 
			
		||||
                             EekTheme                   *theme);
 | 
			
		||||
EekTheme *                  eek_theme_context_get_theme
 | 
			
		||||
                            (EekThemeContext            *context);
 | 
			
		||||
 | 
			
		||||
void                        eek_theme_context_set_resolution
 | 
			
		||||
                            (EekThemeContext            *context,
 | 
			
		||||
                             gdouble                     resolution);
 | 
			
		||||
void                        eek_theme_context_set_default_resolution
 | 
			
		||||
                            (EekThemeContext            *context);
 | 
			
		||||
double                      eek_theme_context_get_resolution
 | 
			
		||||
                            (EekThemeContext            *context);
 | 
			
		||||
void                        eek_theme_context_set_font
 | 
			
		||||
                            (EekThemeContext            *context,
 | 
			
		||||
                             const PangoFontDescription *font);
 | 
			
		||||
const PangoFontDescription *eek_theme_context_get_font
 | 
			
		||||
                            (EekThemeContext            *context);
 | 
			
		||||
 | 
			
		||||
EekThemeNode *              eek_theme_context_get_root_node
 | 
			
		||||
                            (EekThemeContext            *context);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __EEK_THEME_CONTEXT_H__ */
 | 
			
		||||
							
								
								
									
										1864
									
								
								eek/eek-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1864
									
								
								eek/eek-theme-node.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										141
									
								
								eek/eek-theme-node.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								eek/eek-theme-node.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,141 @@
 | 
			
		||||
/* 
 | 
			
		||||
 * Copyright (C) 2010-2011 Daiki Ueno <ueno@unixuser.org>
 | 
			
		||||
 * Copyright (C) 2010-2011 Red Hat, Inc.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is free software; you can redistribute it and/or
 | 
			
		||||
 * modify it under the terms of the GNU Lesser General Public License
 | 
			
		||||
 * as published by the Free Software Foundation; either version 2 of
 | 
			
		||||
 * the License, or (at your option) any later version.
 | 
			
		||||
 * 
 | 
			
		||||
 * This library is distributed in the hope that it will be useful, but
 | 
			
		||||
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | 
			
		||||
 * Lesser General Public License for more details.
 | 
			
		||||
 * 
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public
 | 
			
		||||
 * License along with this library; if not, write to the Free Software
 | 
			
		||||
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | 
			
		||||
 * 02110-1301 USA
 | 
			
		||||
 */
 | 
			
		||||
#ifndef __EEK_THEME_NODE_H__
 | 
			
		||||
#define __EEK_THEME_NODE_H__
 | 
			
		||||
 | 
			
		||||
#include <pango/pango.h>
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:eek-theme-node
 | 
			
		||||
 * @short_description: style information for one node in a tree of
 | 
			
		||||
 * themed objects
 | 
			
		||||
 *
 | 
			
		||||
 * The #EekThemeNode class represents the CSS style information (the
 | 
			
		||||
 * set of CSS properties) for one node in a tree of themed objects. In
 | 
			
		||||
 * typical usage, it represents the style information for a single
 | 
			
		||||
 * #EekElement. A #EekThemeNode is immutable: attributes such as the
 | 
			
		||||
 * CSS classes for the node are passed in at construction. If the
 | 
			
		||||
 * attributes of the node or any parent node change, the node should
 | 
			
		||||
 * be discarded and a new node created.  #EekThemeNode has generic
 | 
			
		||||
 * accessors to look up properties by name and specific accessors for
 | 
			
		||||
 * standard CSS properties that add caching and handling of various
 | 
			
		||||
 * details of the CSS specification. #EekThemeNode also has
 | 
			
		||||
 * convenience functions to help in implementing a #EekElement with
 | 
			
		||||
 * borders and padding.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    EEK_SIDE_TOP,
 | 
			
		||||
    EEK_SIDE_RIGHT,
 | 
			
		||||
    EEK_SIDE_BOTTOM,
 | 
			
		||||
    EEK_SIDE_LEFT
 | 
			
		||||
} EekSide;
 | 
			
		||||
 | 
			
		||||
typedef enum {
 | 
			
		||||
    EEK_CORNER_TOPLEFT,
 | 
			
		||||
    EEK_CORNER_TOPRIGHT,
 | 
			
		||||
    EEK_CORNER_BOTTOMRIGHT,
 | 
			
		||||
    EEK_CORNER_BOTTOMLEFT
 | 
			
		||||
} EekCorner;
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_THEME_NODE (eek_theme_node_get_type())
 | 
			
		||||
#define EEK_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME_NODE, EekThemeNode))
 | 
			
		||||
#define EEK_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
 | 
			
		||||
#define EEK_IS_THEME_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME_NODE))
 | 
			
		||||
#define EEK_IS_THEME_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME_NODE))
 | 
			
		||||
#define EEK_THEME_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME_NODE, EekThemeNodeClass))
 | 
			
		||||
 | 
			
		||||
typedef struct _EekThemeNodeClass EekThemeNodeClass;
 | 
			
		||||
typedef struct _EekThemeNodePrivate EekThemeNodePrivate;
 | 
			
		||||
 | 
			
		||||
GType         eek_theme_node_get_type
 | 
			
		||||
                                 (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
EekThemeNode *eek_theme_node_new (EekThemeContext            *context,
 | 
			
		||||
                                  EekThemeNode               *parent_node,
 | 
			
		||||
                                  /* can be null */ EekTheme *theme,
 | 
			
		||||
                                  /* can be null */ GType     element_type,
 | 
			
		||||
                                  const char                 *element_id,
 | 
			
		||||
                                  const char                 *element_class,
 | 
			
		||||
                                  const char                 *pseudo_class,
 | 
			
		||||
                                  const char                 *inline_style);
 | 
			
		||||
 | 
			
		||||
EekThemeNode *eek_theme_node_get_parent
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
 | 
			
		||||
EekTheme     *eek_theme_node_get_theme
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
 | 
			
		||||
GType         eek_theme_node_get_element_type
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
const char   *eek_theme_node_get_element_id
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
const char   *eek_theme_node_get_element_class
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
const char   *eek_theme_node_get_pseudo_class
 | 
			
		||||
                                 (EekThemeNode               *node);
 | 
			
		||||
 | 
			
		||||
/* Generic getters ... these are not cached so are less efficient. The other
 | 
			
		||||
 * reason for adding the more specific version is that we can handle the
 | 
			
		||||
 * details of the actual CSS rules, which can be complicated, especially
 | 
			
		||||
 * for fonts
 | 
			
		||||
 */
 | 
			
		||||
void          eek_theme_node_get_color
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  const char                 *property_name,
 | 
			
		||||
                                  EekColor                   *color);
 | 
			
		||||
 | 
			
		||||
/* Specific getters for particular properties: cached
 | 
			
		||||
 */
 | 
			
		||||
void          eek_theme_node_get_background_color
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekColor                   *color);
 | 
			
		||||
void          eek_theme_node_get_foreground_color
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekColor                   *color);
 | 
			
		||||
void          eek_theme_node_get_background_gradient
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekGradientType            *type,
 | 
			
		||||
                                  EekColor                   *start,
 | 
			
		||||
                                  EekColor                   *end);
 | 
			
		||||
int           eek_theme_node_get_border_width
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekSide                     side);
 | 
			
		||||
int           eek_theme_node_get_border_radius
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekCorner                   corner);
 | 
			
		||||
void          eek_theme_node_get_border_color
 | 
			
		||||
                                 (EekThemeNode               *node,
 | 
			
		||||
                                  EekSide                     side,
 | 
			
		||||
                                  EekColor                   *color);
 | 
			
		||||
 | 
			
		||||
/* Font rule processing is pretty complicated, so we just hardcode it
 | 
			
		||||
 * under the standard font/font-family/font-size/etc names. This means
 | 
			
		||||
 * you can't have multiple separate styled fonts for a single item,
 | 
			
		||||
 * but that should be OK.
 | 
			
		||||
 */
 | 
			
		||||
const PangoFontDescription *eek_theme_node_get_font (EekThemeNode *node);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __EEK_THEME_NODE_H__ */
 | 
			
		||||
							
								
								
									
										22
									
								
								eek/eek-theme-private.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								eek/eek-theme-private.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
#ifndef __EEK_THEME_PRIVATE_H__
 | 
			
		||||
#define __EEK_THEME_PRIVATE_H__
 | 
			
		||||
 | 
			
		||||
#include <libcroco/libcroco.h>
 | 
			
		||||
#include "eek-theme.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
GPtrArray *_eek_theme_get_matched_properties (EekTheme       *theme,
 | 
			
		||||
                                             EekThemeNode   *node);
 | 
			
		||||
 | 
			
		||||
/* Resolve an URL from the stylesheet to a filename */
 | 
			
		||||
char *_eek_theme_resolve_url (EekTheme      *theme,
 | 
			
		||||
                             CRStyleSheet *base_stylesheet,
 | 
			
		||||
                             const char   *url);
 | 
			
		||||
 | 
			
		||||
CRDeclaration *_eek_theme_parse_declaration_list (const char *str);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __EEK_THEME_PRIVATE_H__ */
 | 
			
		||||
							
								
								
									
										1095
									
								
								eek/eek-theme.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1095
									
								
								eek/eek-theme.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										49
									
								
								eek/eek-theme.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								eek/eek-theme.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
 | 
			
		||||
 | 
			
		||||
#if !defined(__EEK_H_INSIDE__) && !defined(EEK_COMPILATION)
 | 
			
		||||
#error "Only <eek/eek.h> can be included directly."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef __EEK_THEME_H__
 | 
			
		||||
#define __EEK_THEME_H__
 | 
			
		||||
 | 
			
		||||
#include <glib-object.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-types.h"
 | 
			
		||||
 | 
			
		||||
G_BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * SECTION:EekTheme
 | 
			
		||||
 * @short_description: a set of stylesheets
 | 
			
		||||
 *
 | 
			
		||||
 * #EekTheme holds a set of stylesheets. (The "cascade" of the name
 | 
			
		||||
 * Cascading Stylesheets.) An #EekTheme can be set to apply to all the
 | 
			
		||||
 * keyboard elements.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct _EekThemeClass EekThemeClass;
 | 
			
		||||
 | 
			
		||||
#define EEK_TYPE_THEME (eek_theme_get_type())
 | 
			
		||||
#define EEK_THEME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EEK_TYPE_THEME, EekTheme))
 | 
			
		||||
#define EEK_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EEK_TYPE_THEME, EekThemeClass))
 | 
			
		||||
#define EEK_IS_THEME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EEK_TYPE_THEME))
 | 
			
		||||
#define EEK_IS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EEK_TYPE_THEME))
 | 
			
		||||
#define EEK_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EEK_TYPE_THEME, EekThemeClass))
 | 
			
		||||
 | 
			
		||||
GType     eek_theme_get_type          (void) G_GNUC_CONST;
 | 
			
		||||
 | 
			
		||||
EekTheme *eek_theme_new               (const char *application_stylesheet,
 | 
			
		||||
                                       const char *theme_stylesheet,
 | 
			
		||||
                                       const char *default_stylesheet);
 | 
			
		||||
 | 
			
		||||
gboolean  eek_theme_load_stylesheet   (EekTheme   *theme,
 | 
			
		||||
                                       const char *path,
 | 
			
		||||
                                       GError    **error);
 | 
			
		||||
 | 
			
		||||
void      eek_theme_unload_stylesheet (EekTheme   *theme,
 | 
			
		||||
                                       const char *path);
 | 
			
		||||
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* __EEK_THEME_H__ */
 | 
			
		||||
@ -134,7 +134,12 @@ typedef enum
 | 
			
		||||
#define EEK_INVALID_KEYCODE (0)
 | 
			
		||||
    
 | 
			
		||||
typedef struct _EekElement EekElement;
 | 
			
		||||
typedef struct _EekContainer EekContainer;
 | 
			
		||||
typedef struct _EekKey EekKey;
 | 
			
		||||
typedef struct _EekSection EekSection;
 | 
			
		||||
typedef struct _EekKeyboard EekKeyboard;
 | 
			
		||||
typedef struct _EekSymbol EekSymbol;
 | 
			
		||||
typedef struct _EekKeysym EekKeysym;
 | 
			
		||||
typedef struct _EekText EekText;
 | 
			
		||||
typedef struct _EekTheme EekTheme;
 | 
			
		||||
typedef struct _EekThemeContext EekThemeContext;
 | 
			
		||||
@ -146,7 +151,6 @@ typedef struct _EekOutline EekOutline;
 | 
			
		||||
typedef struct _EekColor EekColor;
 | 
			
		||||
 | 
			
		||||
typedef struct _EekboardContextService EekboardContextService;
 | 
			
		||||
typedef struct _LevelKeyboard LevelKeyboard;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekPoint:
 | 
			
		||||
@ -191,6 +195,12 @@ GType      eek_bounds_get_type (void) G_GNUC_CONST;
 | 
			
		||||
EekBounds *eek_bounds_copy     (const EekBounds *bounds);
 | 
			
		||||
void       eek_bounds_free     (EekBounds       *bounds);
 | 
			
		||||
 | 
			
		||||
G_INLINE_FUNC gdouble
 | 
			
		||||
eek_bounds_long_side (EekBounds *bounds)
 | 
			
		||||
{
 | 
			
		||||
    return bounds->width > bounds->height ? bounds->width : bounds->height;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * EekOutline:
 | 
			
		||||
 * @corner_radius: radius of corners of rounded polygon
 | 
			
		||||
 | 
			
		||||
@ -27,14 +27,15 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "eek-xml-layout.h"
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "src/keyboard.h"
 | 
			
		||||
#include "src/symbol.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-keysym.h"
 | 
			
		||||
#include "eek-text.h"
 | 
			
		||||
 | 
			
		||||
#include "squeekboard-resources.h"
 | 
			
		||||
 | 
			
		||||
#include "eek-xml-layout.h"
 | 
			
		||||
 | 
			
		||||
enum {
 | 
			
		||||
    PROP_0,
 | 
			
		||||
    PROP_ID,
 | 
			
		||||
@ -51,8 +52,8 @@ typedef struct _EekXmlLayoutPrivate
 | 
			
		||||
} EekXmlLayoutPrivate;
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_EXTENDED (EekXmlLayout, eek_xml_layout, EEK_TYPE_LAYOUT,
 | 
			
		||||
            0, /* GTypeFlags */
 | 
			
		||||
            G_ADD_PRIVATE(EekXmlLayout)
 | 
			
		||||
			0, /* GTypeFlags */
 | 
			
		||||
			G_ADD_PRIVATE(EekXmlLayout)
 | 
			
		||||
                        G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
 | 
			
		||||
                                               initable_iface_init))
 | 
			
		||||
 | 
			
		||||
@ -66,16 +67,16 @@ static GList        *parse_prerequisites
 | 
			
		||||
                                     (const gchar         *path,
 | 
			
		||||
                                      GError             **error);
 | 
			
		||||
static gboolean      parse_geometry  (const gchar         *path,
 | 
			
		||||
                                      struct squeek_view **views, GArray *outline_array, GHashTable *name_button_hash,
 | 
			
		||||
                                      EekKeyboard         *keyboard,
 | 
			
		||||
                                      GError             **error);
 | 
			
		||||
static gboolean      parse_symbols_with_prerequisites
 | 
			
		||||
                                     (const gchar         *keyboards_dir,
 | 
			
		||||
                                      const gchar         *name,
 | 
			
		||||
                                      LevelKeyboard *keyboard,
 | 
			
		||||
                                      EekKeyboard         *keyboard,
 | 
			
		||||
                                      GList             **loaded,
 | 
			
		||||
                                      GError             **error);
 | 
			
		||||
static gboolean      parse_symbols   (const gchar         *path,
 | 
			
		||||
                                      LevelKeyboard *keyboard,
 | 
			
		||||
                                      EekKeyboard         *keyboard,
 | 
			
		||||
                                      GError             **error);
 | 
			
		||||
 | 
			
		||||
static gboolean      validate        (const gchar        **valid_path_list,
 | 
			
		||||
@ -231,48 +232,40 @@ struct _GeometryParseData {
 | 
			
		||||
    GSList *element_stack;
 | 
			
		||||
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
    struct squeek_view **views;
 | 
			
		||||
    guint view_idx;
 | 
			
		||||
    struct squeek_row *row;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekSection *section;
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
    gint num_columns;
 | 
			
		||||
    gint num_rows;
 | 
			
		||||
    EekOrientation orientation;
 | 
			
		||||
    gdouble corner_radius;
 | 
			
		||||
    GSList *points;
 | 
			
		||||
    gchar *name;
 | 
			
		||||
    EekOutline outline;
 | 
			
		||||
    gchar *outline_id;
 | 
			
		||||
    guint keycode;
 | 
			
		||||
    gchar *oref;
 | 
			
		||||
    gint keycode;
 | 
			
		||||
 | 
			
		||||
    GString *text;
 | 
			
		||||
 | 
			
		||||
    GArray *outline_array;
 | 
			
		||||
 | 
			
		||||
    GHashTable *name_button_hash; // char* -> struct squeek_button*
 | 
			
		||||
    GHashTable *keyname_oref_hash; // char* -> guint
 | 
			
		||||
    GHashTable *outlineid_oref_hash; // char* -> guint
 | 
			
		||||
    GHashTable *key_oref_hash;
 | 
			
		||||
    GHashTable *oref_outline_hash;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _GeometryParseData GeometryParseData;
 | 
			
		||||
 | 
			
		||||
static GeometryParseData *
 | 
			
		||||
geometry_parse_data_new (struct squeek_view **views, GHashTable *name_button_hash, GArray *outline_array)
 | 
			
		||||
geometry_parse_data_new (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    GeometryParseData *data = g_slice_new0 (GeometryParseData);
 | 
			
		||||
 | 
			
		||||
    data->views = views;
 | 
			
		||||
    data->outline_array = outline_array;
 | 
			
		||||
    data->keyname_oref_hash =
 | 
			
		||||
    data->keyboard = g_object_ref (keyboard);
 | 
			
		||||
    data->key_oref_hash =
 | 
			
		||||
        g_hash_table_new_full (g_direct_hash,
 | 
			
		||||
                               g_direct_equal,
 | 
			
		||||
                               NULL,
 | 
			
		||||
                               g_free);
 | 
			
		||||
    data->oref_outline_hash =
 | 
			
		||||
        g_hash_table_new_full (g_str_hash,
 | 
			
		||||
                               g_str_equal,
 | 
			
		||||
                               g_free,
 | 
			
		||||
                               NULL);
 | 
			
		||||
    data->outlineid_oref_hash =
 | 
			
		||||
        g_hash_table_new_full (g_str_hash,
 | 
			
		||||
                               g_str_equal,
 | 
			
		||||
                               g_free,
 | 
			
		||||
                               NULL);
 | 
			
		||||
 | 
			
		||||
    data->name_button_hash = name_button_hash;
 | 
			
		||||
    data->text = g_string_sized_new (BUFSIZE);
 | 
			
		||||
                               (GDestroyNotify)eek_outline_free);
 | 
			
		||||
    data->keycode = 8;
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
@ -280,19 +273,21 @@ geometry_parse_data_new (struct squeek_view **views, GHashTable *name_button_has
 | 
			
		||||
static void
 | 
			
		||||
geometry_parse_data_free (GeometryParseData *data)
 | 
			
		||||
{
 | 
			
		||||
    g_hash_table_destroy (data->keyname_oref_hash);
 | 
			
		||||
    g_hash_table_destroy (data->outlineid_oref_hash);
 | 
			
		||||
    g_string_free (data->text, TRUE);
 | 
			
		||||
    g_object_unref (data->keyboard);
 | 
			
		||||
    g_hash_table_destroy (data->key_oref_hash);
 | 
			
		||||
    g_hash_table_destroy (data->oref_outline_hash);
 | 
			
		||||
    g_slice_free (GeometryParseData, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const gchar *geometry_valid_path_list[] = {
 | 
			
		||||
    "geometry",
 | 
			
		||||
    "button/geometry",
 | 
			
		||||
    "bounds/geometry",
 | 
			
		||||
    "view/geometry",
 | 
			
		||||
    "section/view/geometry",
 | 
			
		||||
    "section/geometry",
 | 
			
		||||
    "outline/geometry",
 | 
			
		||||
    "bounds/section/geometry",
 | 
			
		||||
    "row/section/geometry",
 | 
			
		||||
    "key/row/section/geometry",
 | 
			
		||||
    "bounds/key/row/section/geometry",
 | 
			
		||||
    "point/outline/geometry",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -360,67 +355,83 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        bounds.height = g_strtod (attribute, NULL);
 | 
			
		||||
        data->bounds = bounds;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "view") == 0) {
 | 
			
		||||
        /* Create an empty keyboard to which geometry and symbols
 | 
			
		||||
           information are applied. */
 | 
			
		||||
        struct squeek_view *view = squeek_view_new(data->bounds);
 | 
			
		||||
        data->views[data->view_idx] = view;
 | 
			
		||||
        if (g_strcmp0 (data->element_stack->data, "geometry") == 0)
 | 
			
		||||
            eek_element_set_bounds (EEK_ELEMENT(data->keyboard), &bounds);
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "section") == 0) {
 | 
			
		||||
        gint angle = 0;
 | 
			
		||||
        data->section = eek_keyboard_create_section (data->keyboard);
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "id");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            eek_element_set_name (EEK_ELEMENT(data->section), attribute);
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "angle");
 | 
			
		||||
        if (attribute != NULL) {
 | 
			
		||||
            gint angle;
 | 
			
		||||
            angle = strtol (attribute, NULL, 10);
 | 
			
		||||
            eek_section_set_angle (data->section, angle);
 | 
			
		||||
        }
 | 
			
		||||
        data->row = squeek_view_create_row(data->views[data->view_idx], angle);
 | 
			
		||||
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "button") == 0) {
 | 
			
		||||
        const gchar *base_name = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
    if (g_strcmp0 (element_name, "row") == 0) {
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "orientation");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            data->orientation = strtol (attribute, NULL, 10);
 | 
			
		||||
 | 
			
		||||
        eek_section_add_row (data->section,
 | 
			
		||||
                             data->num_columns,
 | 
			
		||||
                             data->orientation);
 | 
			
		||||
 | 
			
		||||
        data->num_rows++;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "key") == 0) {
 | 
			
		||||
        guint keycode;
 | 
			
		||||
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "name");
 | 
			
		||||
        if (base_name == NULL) {
 | 
			
		||||
        if (attribute == NULL) {
 | 
			
		||||
            g_set_error (error,
 | 
			
		||||
                         G_MARKUP_ERROR,
 | 
			
		||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
			
		||||
                         "no \"name\" attribute for \"button\"");
 | 
			
		||||
                         "no \"name\" attribute for \"key\"");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        gchar *name = g_strdup (attribute);
 | 
			
		||||
 | 
			
		||||
        const gchar *oref_name = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "oref");
 | 
			
		||||
        if (oref_name == NULL) {
 | 
			
		||||
            oref_name = "default";
 | 
			
		||||
        }
 | 
			
		||||
        const gchar *keycode_name = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "keycode");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            keycode = strtol (attribute, NULL, 10);
 | 
			
		||||
        else
 | 
			
		||||
            keycode = data->keycode++;
 | 
			
		||||
 | 
			
		||||
        guint oref = GPOINTER_TO_UINT(g_hash_table_lookup(data->outlineid_oref_hash,
 | 
			
		||||
                                      oref_name));
 | 
			
		||||
        const gchar *name = base_name;
 | 
			
		||||
        g_hash_table_insert (data->keyname_oref_hash,
 | 
			
		||||
                             g_strdup(name),
 | 
			
		||||
                             GUINT_TO_POINTER(oref));
 | 
			
		||||
        data->key = eek_section_create_key (data->section,
 | 
			
		||||
                                            name,
 | 
			
		||||
                                            keycode,
 | 
			
		||||
                                            data->num_columns,
 | 
			
		||||
                                            data->num_rows - 1);
 | 
			
		||||
 | 
			
		||||
        struct squeek_button *button = g_hash_table_lookup(data->name_button_hash, name);
 | 
			
		||||
        // never gets used! this section gets executed before any buttons get defined
 | 
			
		||||
        if (button) {
 | 
			
		||||
            if (keycode_name != NULL) {
 | 
			
		||||
                // This sets the keycode for all buttons,
 | 
			
		||||
                // since they share state
 | 
			
		||||
                // TODO: get rid of this in the parser;
 | 
			
		||||
                // this belongs after keymap is defined
 | 
			
		||||
                struct squeek_key *key = squeek_button_get_key(button);
 | 
			
		||||
                squeek_key_set_keycode(key, strtol (keycode_name, NULL, 10));
 | 
			
		||||
            }
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "oref");
 | 
			
		||||
        if (attribute == NULL) {
 | 
			
		||||
            g_set_error (error,
 | 
			
		||||
                         G_MARKUP_ERROR,
 | 
			
		||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
			
		||||
                         "no \"oref\" attribute for \"key\"");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        g_hash_table_insert (data->key_oref_hash,
 | 
			
		||||
                             data->key,
 | 
			
		||||
                             g_strdup (attribute));
 | 
			
		||||
 | 
			
		||||
        data->num_columns++;
 | 
			
		||||
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
@ -434,7 +445,7 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
                         "no \"id\" attribute for \"outline\"");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        data->outline_id = g_strdup (attribute);
 | 
			
		||||
        data->oref = g_strdup (attribute);
 | 
			
		||||
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "corner-radius");
 | 
			
		||||
@ -479,30 +490,6 @@ geometry_start_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
 out:
 | 
			
		||||
    data->element_stack = g_slist_prepend (data->element_stack,
 | 
			
		||||
                                           g_strdup (element_name));
 | 
			
		||||
    data->text->len = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * eek_keyboard_add_outline:
 | 
			
		||||
 * @keyboard: an #EekKeyboard
 | 
			
		||||
 * @outline: an #EekOutline
 | 
			
		||||
 *
 | 
			
		||||
 * Register an outline of @keyboard.
 | 
			
		||||
 * Returns: an unsigned integer ID of the registered outline, for
 | 
			
		||||
 * later reference
 | 
			
		||||
 */
 | 
			
		||||
static guint
 | 
			
		||||
add_outline (GArray *outline_array,
 | 
			
		||||
                          EekOutline  *outline)
 | 
			
		||||
{
 | 
			
		||||
    EekOutline *_outline;
 | 
			
		||||
 | 
			
		||||
    _outline = eek_outline_copy (outline);
 | 
			
		||||
    g_array_append_val (outline_array, *_outline);
 | 
			
		||||
    /* don't use eek_outline_free here, so as to keep _outline->points */
 | 
			
		||||
    g_slice_free (EekOutline, _outline);
 | 
			
		||||
    return outline_array->len - 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -518,65 +505,20 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
    data->element_stack = g_slist_next (data->element_stack);
 | 
			
		||||
    g_slist_free1 (head);
 | 
			
		||||
 | 
			
		||||
    const gchar *text = g_strndup (data->text->str, data->text->len);
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "view") == 0) {
 | 
			
		||||
        data->view_idx++;
 | 
			
		||||
    if (g_strcmp0 (element_name, "section") == 0) {
 | 
			
		||||
        data->section = NULL;
 | 
			
		||||
        data->num_rows = 0;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "section") == 0) {
 | 
			
		||||
        // Split text on spaces and process each part
 | 
			
		||||
        unsigned head = 0;
 | 
			
		||||
        while (head < strlen(text)) {
 | 
			
		||||
            // Skip to the first non-space character
 | 
			
		||||
            for (; head < strlen(text); head++) {
 | 
			
		||||
                if (text[head] != ' ') {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            unsigned start = head;
 | 
			
		||||
    if (g_strcmp0 (element_name, "key") == 0) {
 | 
			
		||||
        data->key = NULL;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
            // Skip to the first space character
 | 
			
		||||
            for (; head < strlen(text); head++) {
 | 
			
		||||
                if (text[head] == ' ') {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            unsigned end = head;
 | 
			
		||||
 | 
			
		||||
            /// Reached the end
 | 
			
		||||
            if (start == end) {
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            gchar *name = g_strndup (&text[start], end - start);
 | 
			
		||||
            struct squeek_button *button = g_hash_table_lookup(data->name_button_hash, name);
 | 
			
		||||
            if (!button) {
 | 
			
		||||
                // Save button name together with its level,
 | 
			
		||||
                // to account for buttons with the same name in multiple levels
 | 
			
		||||
                guint keycode = data->keycode++;
 | 
			
		||||
 | 
			
		||||
                guint oref = GPOINTER_TO_UINT(g_hash_table_lookup(data->keyname_oref_hash, name));
 | 
			
		||||
                // default value gives idx 0, which is guaranteed to be occupied
 | 
			
		||||
                button = squeek_row_create_button (data->row, keycode, oref);
 | 
			
		||||
                g_hash_table_insert (data->name_button_hash,
 | 
			
		||||
                                     g_strdup(name),
 | 
			
		||||
                                     button);
 | 
			
		||||
            } else {
 | 
			
		||||
                struct squeek_button *new_button = squeek_row_create_button_with_state(data->row, button);
 | 
			
		||||
                if (!new_button) {
 | 
			
		||||
                    g_set_error (error,
 | 
			
		||||
                                 G_MARKUP_ERROR,
 | 
			
		||||
                                 G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
			
		||||
                                 "Couldn't create a shared button");
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data->row = NULL;
 | 
			
		||||
        data->num_rows = 0;
 | 
			
		||||
    if (g_strcmp0 (element_name, "row") == 0) {
 | 
			
		||||
        data->num_columns = 0;
 | 
			
		||||
        data->orientation = EEK_ORIENTATION_HORIZONTAL;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -599,30 +541,19 @@ geometry_end_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
        g_slist_free (data->points);
 | 
			
		||||
        data->points = NULL;
 | 
			
		||||
 | 
			
		||||
        guint oref = add_outline (data->outline_array, outline);
 | 
			
		||||
        g_hash_table_insert (data->oref_outline_hash,
 | 
			
		||||
                             g_strdup (data->oref),
 | 
			
		||||
                             outline);
 | 
			
		||||
 | 
			
		||||
        g_hash_table_insert (data->outlineid_oref_hash,
 | 
			
		||||
                             data->outline_id,
 | 
			
		||||
                             GUINT_TO_POINTER(oref));
 | 
			
		||||
        g_free (data->oref);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
geometry_text_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
                       const gchar         *text,
 | 
			
		||||
                       gsize                text_len,
 | 
			
		||||
                       gpointer             user_data,
 | 
			
		||||
                       GError             **error)
 | 
			
		||||
{
 | 
			
		||||
    GeometryParseData *data = user_data;
 | 
			
		||||
    g_string_append_len (data->text, text, (gssize)text_len);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const GMarkupParser geometry_parser = {
 | 
			
		||||
    geometry_start_element_callback,
 | 
			
		||||
    geometry_end_element_callback,
 | 
			
		||||
    geometry_text_callback,
 | 
			
		||||
    0,
 | 
			
		||||
    0,
 | 
			
		||||
    0
 | 
			
		||||
};
 | 
			
		||||
@ -631,22 +562,24 @@ struct _SymbolsParseData {
 | 
			
		||||
    GSList *element_stack;
 | 
			
		||||
    GString *text;
 | 
			
		||||
 | 
			
		||||
    LevelKeyboard *keyboard;
 | 
			
		||||
    struct squeek_view *view;
 | 
			
		||||
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekKey *key;
 | 
			
		||||
    GSList *symbols;
 | 
			
		||||
    gchar *label;
 | 
			
		||||
    gchar *icon;
 | 
			
		||||
    gchar *tooltip;
 | 
			
		||||
    EekSymbolCategory category;
 | 
			
		||||
    guint keyval;
 | 
			
		||||
    gint groups;
 | 
			
		||||
};
 | 
			
		||||
typedef struct _SymbolsParseData SymbolsParseData;
 | 
			
		||||
 | 
			
		||||
static SymbolsParseData *
 | 
			
		||||
symbols_parse_data_new (LevelKeyboard *keyboard)
 | 
			
		||||
symbols_parse_data_new (EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    SymbolsParseData *data = g_slice_new0 (SymbolsParseData);
 | 
			
		||||
 | 
			
		||||
    data->keyboard = keyboard;
 | 
			
		||||
    data->keyboard = g_object_ref (keyboard);
 | 
			
		||||
    data->text = g_string_sized_new (BUFSIZE);
 | 
			
		||||
    return data;
 | 
			
		||||
}
 | 
			
		||||
@ -654,14 +587,19 @@ symbols_parse_data_new (LevelKeyboard *keyboard)
 | 
			
		||||
static void
 | 
			
		||||
symbols_parse_data_free (SymbolsParseData *data)
 | 
			
		||||
{
 | 
			
		||||
    g_object_unref (data->keyboard);
 | 
			
		||||
    g_string_free (data->text, TRUE);
 | 
			
		||||
    g_slice_free (SymbolsParseData, data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const gchar *symbols_valid_path_list[] = {
 | 
			
		||||
    "symbols",
 | 
			
		||||
    "symbol/symbols",
 | 
			
		||||
    "include/symbols",
 | 
			
		||||
    "key/symbols",
 | 
			
		||||
    "text/key/symbols",
 | 
			
		||||
    "keysym/key/symbols",
 | 
			
		||||
    "symbol/key/symbols",
 | 
			
		||||
    "invalid/key/symbols",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
@ -682,7 +620,53 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
                   error))
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "symbol") == 0) {
 | 
			
		||||
    if (g_strcmp0 (element_name, "key") == 0) {
 | 
			
		||||
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "name");
 | 
			
		||||
        if (attribute == NULL) {
 | 
			
		||||
            g_set_error (error,
 | 
			
		||||
                         G_MARKUP_ERROR,
 | 
			
		||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
			
		||||
                         "no \"name\" attribute for \"key\"");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data->key = eek_keyboard_find_key_by_name (data->keyboard,
 | 
			
		||||
                                                   attribute);
 | 
			
		||||
        if (data->key == NULL) {
 | 
			
		||||
            g_set_error (error,
 | 
			
		||||
                         G_MARKUP_ERROR,
 | 
			
		||||
                         G_MARKUP_ERROR_INVALID_CONTENT,
 | 
			
		||||
                         "no such key %s", attribute);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "groups");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            data->groups = strtol (attribute, NULL, 10);
 | 
			
		||||
        else
 | 
			
		||||
            data->groups = 1;
 | 
			
		||||
        data->symbols = NULL;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "keysym") == 0) {
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "keyval");
 | 
			
		||||
        if (attribute == NULL) {
 | 
			
		||||
            g_set_error (error,
 | 
			
		||||
                         G_MARKUP_ERROR,
 | 
			
		||||
                         G_MARKUP_ERROR_MISSING_ATTRIBUTE,
 | 
			
		||||
                         "no \"keyval\" attribute for \"keysym\"");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        data->keyval = strtoul (attribute, NULL, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "symbol") == 0 ||
 | 
			
		||||
        g_strcmp0 (element_name, "keysym") == 0 ||
 | 
			
		||||
        g_strcmp0 (element_name, "text") == 0) {
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "label");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
@ -697,8 +681,16 @@ symbols_start_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
                                   "tooltip");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            data->tooltip = g_strdup (attribute);
 | 
			
		||||
 | 
			
		||||
        attribute = get_attribute (attribute_names, attribute_values,
 | 
			
		||||
                                   "category");
 | 
			
		||||
        if (attribute != NULL)
 | 
			
		||||
            data->category = strtoul (attribute, NULL, 10);
 | 
			
		||||
        else
 | 
			
		||||
            data->category = EEK_SYMBOL_CATEGORY_KEYNAME;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
    data->element_stack = g_slist_prepend (data->element_stack,
 | 
			
		||||
                                           g_strdup (element_name));
 | 
			
		||||
    data->text->len = 0;
 | 
			
		||||
@ -713,42 +705,81 @@ symbols_end_element_callback (GMarkupParseContext *pcontext,
 | 
			
		||||
    SymbolsParseData *data = user_data;
 | 
			
		||||
    GSList *head = data->element_stack;
 | 
			
		||||
    gchar *text;
 | 
			
		||||
    gint i;
 | 
			
		||||
 | 
			
		||||
    g_free (head->data);
 | 
			
		||||
    data->element_stack = g_slist_next (data->element_stack);
 | 
			
		||||
    g_slist_free1 (head);
 | 
			
		||||
 | 
			
		||||
    // TODO: this could all be moved to text handler
 | 
			
		||||
    text = g_strndup (data->text->str, data->text->len);
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "symbol") == 0) {
 | 
			
		||||
 | 
			
		||||
        gchar *name = text;
 | 
			
		||||
        struct squeek_button *button = eek_keyboard_find_button_by_name (data->keyboard,
 | 
			
		||||
                                                   name);
 | 
			
		||||
        if (button) {
 | 
			
		||||
            squeek_key_add_symbol(
 | 
			
		||||
                squeek_button_get_key(button),
 | 
			
		||||
                element_name,
 | 
			
		||||
                text,
 | 
			
		||||
                data->keyval,
 | 
			
		||||
                data->label,
 | 
			
		||||
                data->icon,
 | 
			
		||||
                data->tooltip
 | 
			
		||||
            );
 | 
			
		||||
    if (g_strcmp0 (element_name, "key") == 0) {
 | 
			
		||||
        if (!data->key) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data->keyval = 0;
 | 
			
		||||
        g_free(data->label);
 | 
			
		||||
        data->label = NULL;
 | 
			
		||||
        g_free(data->icon);
 | 
			
		||||
        data->icon = NULL;
 | 
			
		||||
        g_free(data->tooltip);
 | 
			
		||||
        data->tooltip = NULL;
 | 
			
		||||
        gint num_symbols = g_slist_length (data->symbols);
 | 
			
		||||
        gint levels = num_symbols / data->groups;
 | 
			
		||||
        EekSymbolMatrix *matrix = eek_symbol_matrix_new (data->groups,
 | 
			
		||||
                                                         levels);
 | 
			
		||||
        head = data->symbols = g_slist_reverse (data->symbols);
 | 
			
		||||
        for (i = 0; i < num_symbols; i++) {
 | 
			
		||||
            if (head && head->data) {
 | 
			
		||||
                matrix->data[i] = head->data;
 | 
			
		||||
                head = g_slist_next (head);
 | 
			
		||||
            } else
 | 
			
		||||
                matrix->data[i] = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        g_slist_free (data->symbols);
 | 
			
		||||
        data->symbols = NULL;
 | 
			
		||||
 | 
			
		||||
        eek_key_set_symbol_matrix (data->key, matrix);
 | 
			
		||||
        eek_symbol_matrix_free (matrix);
 | 
			
		||||
        data->key = NULL;
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "symbol") == 0 ||
 | 
			
		||||
        g_strcmp0 (element_name, "keysym") == 0 ||
 | 
			
		||||
        g_strcmp0 (element_name, "text") == 0) {
 | 
			
		||||
        EekSymbol *symbol;
 | 
			
		||||
 | 
			
		||||
        if (g_strcmp0 (element_name, "keysym") == 0) {
 | 
			
		||||
            EekKeysym *keysym;
 | 
			
		||||
            if (data->keyval != EEK_INVALID_KEYSYM)
 | 
			
		||||
                keysym = eek_keysym_new (data->keyval);
 | 
			
		||||
            else
 | 
			
		||||
                keysym = eek_keysym_new_from_name (text);
 | 
			
		||||
            symbol = EEK_SYMBOL(keysym);
 | 
			
		||||
        } else if (g_strcmp0 (element_name, "text") == 0) {
 | 
			
		||||
            symbol = EEK_SYMBOL(eek_text_new (text));
 | 
			
		||||
        } else {
 | 
			
		||||
            symbol = eek_symbol_new (text);
 | 
			
		||||
            eek_symbol_set_category (symbol, EEK_SYMBOL_CATEGORY_KEYNAME);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (data->label) {
 | 
			
		||||
            eek_symbol_set_label (symbol, data->label);
 | 
			
		||||
            g_free (data->label);
 | 
			
		||||
            data->label = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (data->icon) {
 | 
			
		||||
            eek_symbol_set_icon_name (symbol, data->icon);
 | 
			
		||||
            g_free (data->icon);
 | 
			
		||||
            data->icon = NULL;
 | 
			
		||||
        }
 | 
			
		||||
        if (data->tooltip) {
 | 
			
		||||
            eek_symbol_set_tooltip (symbol, data->tooltip);
 | 
			
		||||
            g_free (data->tooltip);
 | 
			
		||||
            data->tooltip = NULL;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        data->symbols = g_slist_prepend (data->symbols, symbol);
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (element_name, "invalid") == 0) {
 | 
			
		||||
        data->symbols = g_slist_prepend (data->symbols, NULL);
 | 
			
		||||
        goto out;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -860,37 +891,31 @@ static const GMarkupParser prerequisites_parser = {
 | 
			
		||||
    0
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LevelKeyboard *
 | 
			
		||||
eek_xml_layout_real_create_keyboard (EekLayout *self,
 | 
			
		||||
                                     EekboardContextService *manager)
 | 
			
		||||
static EekKeyboard *
 | 
			
		||||
eek_xml_layout_real_create_keyboard (EekboardContextService *manager,
 | 
			
		||||
                                     EekLayout *self,
 | 
			
		||||
                                     gdouble    initial_width,
 | 
			
		||||
                                     gdouble    initial_height)
 | 
			
		||||
{
 | 
			
		||||
    EekXmlLayout *layout = EEK_XML_LAYOUT (self);
 | 
			
		||||
    EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (layout);
 | 
			
		||||
    gboolean retval;
 | 
			
		||||
 | 
			
		||||
    /* Create an empty keyboard to which geometry and symbols
 | 
			
		||||
       information are applied. */
 | 
			
		||||
    EekKeyboard *keyboard = g_object_new (EEK_TYPE_KEYBOARD, "layout", layout, NULL);
 | 
			
		||||
    keyboard->manager = manager;
 | 
			
		||||
 | 
			
		||||
    /* Read geometry information. */
 | 
			
		||||
    gchar *filename = g_strdup_printf ("%s.xml", priv->desc->geometry);
 | 
			
		||||
    gchar *path = g_build_filename (priv->keyboards_dir, "geometry", filename, NULL);
 | 
			
		||||
    g_free (filename);
 | 
			
		||||
 | 
			
		||||
    GArray *outline_array = g_array_new (FALSE, TRUE, sizeof (EekOutline));
 | 
			
		||||
 | 
			
		||||
    // char* -> struct squeek_button*
 | 
			
		||||
    GHashTable *name_button_hash =
 | 
			
		||||
            g_hash_table_new_full (g_str_hash,
 | 
			
		||||
                                   g_str_equal,
 | 
			
		||||
                                   g_free,
 | 
			
		||||
                                   NULL);
 | 
			
		||||
    // One view for each level
 | 
			
		||||
    struct squeek_view *views[4] = {0};
 | 
			
		||||
 | 
			
		||||
    GError *error = NULL;
 | 
			
		||||
    retval = parse_geometry (path, views, outline_array, name_button_hash, &error);
 | 
			
		||||
    retval = parse_geometry (path, keyboard, &error);
 | 
			
		||||
    g_free (path);
 | 
			
		||||
    if (!retval) {
 | 
			
		||||
        for (uint i = 0; i < 4; i++) {
 | 
			
		||||
            g_object_unref (views[i]);
 | 
			
		||||
        }
 | 
			
		||||
        g_object_unref (keyboard);
 | 
			
		||||
        g_warning ("can't parse geometry file %s: %s",
 | 
			
		||||
                   priv->desc->geometry,
 | 
			
		||||
                   error->message);
 | 
			
		||||
@ -898,12 +923,6 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    LevelKeyboard *keyboard = level_keyboard_new(manager, views, name_button_hash);
 | 
			
		||||
 | 
			
		||||
    keyboard->outline_array = outline_array;
 | 
			
		||||
    // FIXME: are symbols shared betwen views?
 | 
			
		||||
 | 
			
		||||
    /* Read symbols information. */
 | 
			
		||||
    GList *loaded = NULL;
 | 
			
		||||
    retval = parse_symbols_with_prerequisites (priv->keyboards_dir,
 | 
			
		||||
@ -913,13 +932,7 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
 | 
			
		||||
                                               &error);
 | 
			
		||||
    g_list_free_full (loaded, g_free);
 | 
			
		||||
    if (!retval) {
 | 
			
		||||
        for (uint i = 0; i < 4; i++) {
 | 
			
		||||
            if (views[i]) {
 | 
			
		||||
                g_object_unref(views[i]);
 | 
			
		||||
                views[i] = NULL;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //g_object_unref (view);
 | 
			
		||||
        g_object_unref (keyboard);
 | 
			
		||||
        g_warning ("can't parse symbols file %s: %s",
 | 
			
		||||
                   priv->desc->symbols,
 | 
			
		||||
                   error->message);
 | 
			
		||||
@ -927,11 +940,11 @@ eek_xml_layout_real_create_keyboard (EekLayout *self,
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (uint i = 0; i < 4; i++) {
 | 
			
		||||
        if (views[i]) {
 | 
			
		||||
            squeek_view_place_contents(views[i], keyboard);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    eek_layout_place_sections(keyboard);
 | 
			
		||||
 | 
			
		||||
    /* Use pre-defined modifier mask here. */
 | 
			
		||||
    eek_keyboard_set_num_lock_mask (keyboard, EEK_MOD2_MASK);
 | 
			
		||||
    eek_keyboard_set_alt_gr_mask (keyboard, EEK_BUTTON1_MASK);
 | 
			
		||||
 | 
			
		||||
    return keyboard;
 | 
			
		||||
}
 | 
			
		||||
@ -979,7 +992,7 @@ static void
 | 
			
		||||
eek_xml_layout_finalize (GObject *object)
 | 
			
		||||
{
 | 
			
		||||
    EekXmlLayoutPrivate *priv = eek_xml_layout_get_instance_private (
 | 
			
		||||
            EEK_XML_LAYOUT (object));
 | 
			
		||||
		    EEK_XML_LAYOUT (object));
 | 
			
		||||
 | 
			
		||||
    g_free (priv->id);
 | 
			
		||||
 | 
			
		||||
@ -994,18 +1007,21 @@ eek_xml_layout_finalize (GObject *object)
 | 
			
		||||
static void
 | 
			
		||||
eek_xml_layout_class_init (EekXmlLayoutClass *klass)
 | 
			
		||||
{
 | 
			
		||||
    EekLayoutClass *layout_class = EEK_LAYOUT_CLASS (klass);
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    layout_class->create_keyboard = eek_xml_layout_real_create_keyboard;
 | 
			
		||||
 | 
			
		||||
    gobject_class->set_property = eek_xml_layout_set_property;
 | 
			
		||||
    gobject_class->get_property = eek_xml_layout_get_property;
 | 
			
		||||
    gobject_class->finalize = eek_xml_layout_finalize;
 | 
			
		||||
 | 
			
		||||
    pspec = g_param_spec_string ("id",
 | 
			
		||||
                 "ID",
 | 
			
		||||
                 "ID",
 | 
			
		||||
                 NULL,
 | 
			
		||||
                 G_PARAM_CONSTRUCT_ONLY |
 | 
			
		||||
				 "ID",
 | 
			
		||||
				 "ID",
 | 
			
		||||
				 NULL,
 | 
			
		||||
				 G_PARAM_CONSTRUCT_ONLY |
 | 
			
		||||
                                 G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class, PROP_ID, pspec);
 | 
			
		||||
}
 | 
			
		||||
@ -1117,10 +1133,13 @@ eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
parse_geometry (const gchar *path, struct squeek_view **views, GArray *outline_array, GHashTable *name_button_hash, GError **error)
 | 
			
		||||
parse_geometry (const gchar *path, EekKeyboard *keyboard, GError **error)
 | 
			
		||||
{
 | 
			
		||||
    GeometryParseData *data;
 | 
			
		||||
    GMarkupParseContext *pcontext;
 | 
			
		||||
    GHashTable *oref_hash;
 | 
			
		||||
    GHashTableIter iter;
 | 
			
		||||
    gpointer k, v;
 | 
			
		||||
    GFile *file;
 | 
			
		||||
    GFileInputStream *input;
 | 
			
		||||
    gboolean retval;
 | 
			
		||||
@ -1134,7 +1153,7 @@ parse_geometry (const gchar *path, struct squeek_view **views, GArray *outline_a
 | 
			
		||||
    if (input == NULL)
 | 
			
		||||
        return FALSE;
 | 
			
		||||
 | 
			
		||||
    data = geometry_parse_data_new (views, name_button_hash, outline_array);
 | 
			
		||||
    data = geometry_parse_data_new (keyboard);
 | 
			
		||||
    pcontext = g_markup_parse_context_new (&geometry_parser,
 | 
			
		||||
                                           0,
 | 
			
		||||
                                           data,
 | 
			
		||||
@ -1149,29 +1168,23 @@ parse_geometry (const gchar *path, struct squeek_view **views, GArray *outline_a
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* Resolve outline references. */
 | 
			
		||||
    /*
 | 
			
		||||
     * GHashTable *oref_hash;
 | 
			
		||||
    GHashTableIter iter;
 | 
			
		||||
    gpointer k, v;
 | 
			
		||||
 | 
			
		||||
    oref_hash = g_hash_table_new (g_str_hash, g_str_equal);
 | 
			
		||||
    g_hash_table_iter_init (&iter, data->oref_outline_hash);
 | 
			
		||||
    while (g_hash_table_iter_next (&iter, &k, &v)) {
 | 
			
		||||
        EekOutline *outline = v;
 | 
			
		||||
        gulong oref;
 | 
			
		||||
 | 
			
		||||
        oref = add_outline (outline_array, outline);
 | 
			
		||||
        oref = eek_keyboard_add_outline (data->keyboard, outline);
 | 
			
		||||
        g_hash_table_insert (oref_hash, k, GUINT_TO_POINTER(oref));
 | 
			
		||||
    }*/
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
    g_hash_table_iter_init (&iter, data->key_oref_hash);
 | 
			
		||||
    while (g_hash_table_iter_next (&iter, &k, &v)) {
 | 
			
		||||
        gpointer oref;
 | 
			
		||||
        if (g_hash_table_lookup_extended (oref_hash, v, NULL, &oref))
 | 
			
		||||
            eek_key_set_oref (EEK_KEY(k), GPOINTER_TO_UINT(oref));
 | 
			
		||||
    }*/
 | 
			
		||||
//    g_hash_table_destroy (oref_hash);
 | 
			
		||||
    }
 | 
			
		||||
    g_hash_table_destroy (oref_hash);
 | 
			
		||||
 | 
			
		||||
    geometry_parse_data_free (data);
 | 
			
		||||
    return TRUE;
 | 
			
		||||
@ -1180,7 +1193,7 @@ parse_geometry (const gchar *path, struct squeek_view **views, GArray *outline_a
 | 
			
		||||
static gboolean
 | 
			
		||||
parse_symbols_with_prerequisites (const gchar *keyboards_dir,
 | 
			
		||||
                                  const gchar *name,
 | 
			
		||||
                                  LevelKeyboard *keyboard,
 | 
			
		||||
                                  EekKeyboard *keyboard,
 | 
			
		||||
                                  GList     **loaded,
 | 
			
		||||
                                  GError     **error)
 | 
			
		||||
{
 | 
			
		||||
@ -1230,7 +1243,7 @@ parse_symbols_with_prerequisites (const gchar *keyboards_dir,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static gboolean
 | 
			
		||||
parse_symbols (const gchar *path, LevelKeyboard *keyboard, GError **error)
 | 
			
		||||
parse_symbols (const gchar *path, EekKeyboard *keyboard, GError **error)
 | 
			
		||||
{
 | 
			
		||||
    SymbolsParseData *data;
 | 
			
		||||
    GMarkupParseContext *pcontext;
 | 
			
		||||
@ -1345,7 +1358,7 @@ validate (const gchar **valid_path_list,
 | 
			
		||||
          GSList       *element_stack,
 | 
			
		||||
          GError      **error)
 | 
			
		||||
{
 | 
			
		||||
    guint i;
 | 
			
		||||
    gint i;
 | 
			
		||||
    gchar *element_path;
 | 
			
		||||
    GSList *head, *p;
 | 
			
		||||
    GString *string;
 | 
			
		||||
 | 
			
		||||
@ -62,8 +62,5 @@ GList              *eek_xml_list_keyboards     (void);
 | 
			
		||||
EekXmlKeyboardDesc *eek_xml_keyboard_desc_copy (EekXmlKeyboardDesc *desc);
 | 
			
		||||
void                eek_xml_keyboard_desc_free (EekXmlKeyboardDesc *desc);
 | 
			
		||||
 | 
			
		||||
LevelKeyboard *
 | 
			
		||||
eek_xml_layout_real_create_keyboard (EekLayout *self,
 | 
			
		||||
                                     EekboardContextService *manager);
 | 
			
		||||
G_END_DECLS
 | 
			
		||||
#endif  /* EEK_XML_LAYOUT_H */
 | 
			
		||||
 | 
			
		||||
@ -23,8 +23,14 @@
 | 
			
		||||
#define __EEK_H_INSIDE__ 1
 | 
			
		||||
 | 
			
		||||
#include "eek-keyboard.h"
 | 
			
		||||
#include "eek-section.h"
 | 
			
		||||
#include "eek-key.h"
 | 
			
		||||
#include "eek-layout.h"
 | 
			
		||||
#include "eek-symbol.h"
 | 
			
		||||
#include "eek-keysym.h"
 | 
			
		||||
#include "eek-text.h"
 | 
			
		||||
#include "eek-serializable.h"
 | 
			
		||||
#include "eek-theme.h"
 | 
			
		||||
 | 
			
		||||
void eek_init (void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ else:
 | 
			
		||||
 | 
			
		||||
table = dict()
 | 
			
		||||
for line in in_stream:
 | 
			
		||||
    match = re.match(r'\s*(0x[0-9A-F]+)\s+"(.*)"\s+(\S*)', line, re.I)
 | 
			
		||||
    match = re.match(r'\s*(0x[0-9A-F]+)\s+(\S*)\s+(\S*)', line, re.I)
 | 
			
		||||
    if match:
 | 
			
		||||
        table[int(match.group(1), 16)] = (match.group(2), match.group(3))
 | 
			
		||||
 | 
			
		||||
@ -42,8 +42,8 @@ sys.stdout.write("static const EekKeysymEntry %s[] = {\n" %
 | 
			
		||||
 | 
			
		||||
for index, (keysym, (l, c)) in enumerate([(keysym, table[keysym])
 | 
			
		||||
                                          for keysym in sorted(table.keys())]):
 | 
			
		||||
    sys.stdout.write("    { 0x%X, \"%s\" }" %
 | 
			
		||||
                     (keysym, l))
 | 
			
		||||
    sys.stdout.write("    { 0x%X, %s, %s }" %
 | 
			
		||||
                     (keysym, l, c))
 | 
			
		||||
    if index < len(table) - 1:
 | 
			
		||||
        sys.stdout.write(",")
 | 
			
		||||
    sys.stdout.write("\n")
 | 
			
		||||
 | 
			
		||||
@ -1,13 +1,35 @@
 | 
			
		||||
gnome = import('gnome')
 | 
			
		||||
 | 
			
		||||
enum_headers = [
 | 
			
		||||
  'eek-symbol.h',
 | 
			
		||||
  'eek-types.h',
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
enums = gnome.mkenums_simple('eek-enumtypes', sources: enum_headers)
 | 
			
		||||
 | 
			
		||||
marshalers = gnome.genmarshal(
 | 
			
		||||
  'eek-marshalers',
 | 
			
		||||
  sources: ['eek-marshalers.list'],
 | 
			
		||||
  prefix: '_eek_marshal',
 | 
			
		||||
  internal: true,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
python = find_program('python3')
 | 
			
		||||
 | 
			
		||||
gen_keysym_entries_special = generator(
 | 
			
		||||
  python,
 | 
			
		||||
  arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'special_keysym_entries', '@INPUT@'],
 | 
			
		||||
  capture: true,
 | 
			
		||||
  output: 'eek-@BASENAME@.h',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
gen_keysym_entries_unicode = generator(
 | 
			
		||||
  python,
 | 
			
		||||
  arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'unicode_keysym_entries', '@INPUT@'],
 | 
			
		||||
  capture: true,
 | 
			
		||||
  output: 'eek-@BASENAME@.h',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
gen_keysym_entries_xkeysym = generator(
 | 
			
		||||
  python,
 | 
			
		||||
  arguments: ['@CURRENT_SOURCE_DIR@/gen-keysym-entries.py', 'xkeysym_keysym_entries', '@INPUT@'],
 | 
			
		||||
@ -16,5 +38,7 @@ gen_keysym_entries_xkeysym = generator(
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
keysym_entries = [
 | 
			
		||||
  gen_keysym_entries_special.process('./special-keysym-entries.txt'),
 | 
			
		||||
  gen_keysym_entries_unicode.process('./unicode-keysym-entries.txt'),
 | 
			
		||||
  gen_keysym_entries_xkeysym.process('./xkeysym-keysym-entries.txt'),
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								eek/special-keysym-entries.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								eek/special-keysym-entries.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,62 @@
 | 
			
		||||
0x20 "" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0x8A3 "horiz\nconn" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE50 "ˋ" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE51 "ˊ" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE52 "ˆ" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE53 "~" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE54 "ˉ" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE55 "˘" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE56 "˙" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE57 "¨" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE58 "˚" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE59 "˝" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE5A "ˇ" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE5B "¸" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFE5C "˛" EEK_SYMBOL_CATEGORY_LETTER
 | 
			
		||||
0xFF14 "Scroll\nLock" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF20 "Compose" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF55 "Page\nUp" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF56 "Page\nDown" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF7E "AltGr" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF7F "Num\nLock" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF8D "Enter" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF95 "Home" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF96 "Left" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF97 "Up" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF98 "Right" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF99 "Down" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF9C "End" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF9D "Begin" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF9E "Ins" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
0xFF9F "Del" EEK_SYMBOL_CATEGORY_FUNCTION
 | 
			
		||||
# aliases
 | 
			
		||||
0xFE03 "123" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFE04 "⇮" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFE05 "⇮" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFE08 "Next" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFE0A "Prev" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF08 "←" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF09 "⇥" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFE20 "⇤" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF0D "↵" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF1B "Esc" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE1 "⇧" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE2 "⇧" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE3 "Ctrl" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE4 "Ctrl" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE5 "⇪" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE9 "Alt" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFEA "Alt" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE7 "Meta" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFE8 "Meta" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFEB "Super" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFEC "Super" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFED "Hyper" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFFEE "Hyper" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF2A "半" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xFF21 "漢" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
0xff51 "⇠" EEK_SYMBOL_CATEGORY_KEYNAME #			1
 | 
			
		||||
0xff52 "⇡" EEK_SYMBOL_CATEGORY_KEYNAME #			1
 | 
			
		||||
0xff53 "⇢" EEK_SYMBOL_CATEGORY_KEYNAME #			1
 | 
			
		||||
0xff54 "⇣" EEK_SYMBOL_CATEGORY_KEYNAME #			1
 | 
			
		||||
0xff30 "英" EEK_SYMBOL_CATEGORY_KEYNAME
 | 
			
		||||
							
								
								
									
										826
									
								
								eek/unicode-keysym-entries.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										826
									
								
								eek/unicode-keysym-entries.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,826 @@
 | 
			
		||||
# This file is derived from gdkkeyuni.c in GTK+.  Thanks for the
 | 
			
		||||
# team.  The original comments are below:
 | 
			
		||||
 | 
			
		||||
#  Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 | 
			
		||||
#  file for a list of people on the GTK+ Team.  See the ChangeLog
 | 
			
		||||
#  files for a list of changes.  These files are distributed with
 | 
			
		||||
#  GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 | 
			
		||||
 | 
			
		||||
#  Thanks to Markus G. Kuhn <mkuhn@acm.org> for the ksysym<->Unicode
 | 
			
		||||
#  mapping functions, from the xterm sources.
 | 
			
		||||
 | 
			
		||||
#  These tables could be compressed by contiguous ranges, but the
 | 
			
		||||
#  benefit of doing so is smallish. It would save about ~1000 bytes
 | 
			
		||||
#  total.
 | 
			
		||||
 | 
			
		||||
0x01a1 "Ą" EEK_SYMBOL_CATEGORY_LETTER #                     Aogonek Ą LATIN CAPITAL LETTER A WITH OGONEK 
 | 
			
		||||
0x01a2 "˘" EEK_SYMBOL_CATEGORY_LETTER #                       breve ˘ BREVE 
 | 
			
		||||
0x01a3 "Ł" EEK_SYMBOL_CATEGORY_LETTER #                     Lstroke Ł LATIN CAPITAL LETTER L WITH STROKE 
 | 
			
		||||
0x01a5 "Ľ" EEK_SYMBOL_CATEGORY_LETTER #                      Lcaron Ľ LATIN CAPITAL LETTER L WITH CARON 
 | 
			
		||||
0x01a6 "Ś" EEK_SYMBOL_CATEGORY_LETTER #                      Sacute Ś LATIN CAPITAL LETTER S WITH ACUTE 
 | 
			
		||||
0x01a9 "Š" EEK_SYMBOL_CATEGORY_LETTER #                      Scaron Š LATIN CAPITAL LETTER S WITH CARON 
 | 
			
		||||
0x01aa "Ş" EEK_SYMBOL_CATEGORY_LETTER #                    Scedilla Ş LATIN CAPITAL LETTER S WITH CEDILLA 
 | 
			
		||||
0x01ab "Ť" EEK_SYMBOL_CATEGORY_LETTER #                      Tcaron Ť LATIN CAPITAL LETTER T WITH CARON 
 | 
			
		||||
0x01ac "Ź" EEK_SYMBOL_CATEGORY_LETTER #                      Zacute Ź LATIN CAPITAL LETTER Z WITH ACUTE 
 | 
			
		||||
0x01ae "Ž" EEK_SYMBOL_CATEGORY_LETTER #                      Zcaron Ž LATIN CAPITAL LETTER Z WITH CARON 
 | 
			
		||||
0x01af "Ż" EEK_SYMBOL_CATEGORY_LETTER #                   Zabovedot Ż LATIN CAPITAL LETTER Z WITH DOT ABOVE 
 | 
			
		||||
0x01b1 "ą" EEK_SYMBOL_CATEGORY_LETTER #                     aogonek ą LATIN SMALL LETTER A WITH OGONEK 
 | 
			
		||||
0x01b2 "˛" EEK_SYMBOL_CATEGORY_LETTER #                      ogonek ˛ OGONEK 
 | 
			
		||||
0x01b3 "ł" EEK_SYMBOL_CATEGORY_LETTER #                     lstroke ł LATIN SMALL LETTER L WITH STROKE 
 | 
			
		||||
0x01b5 "ľ" EEK_SYMBOL_CATEGORY_LETTER #                      lcaron ľ LATIN SMALL LETTER L WITH CARON 
 | 
			
		||||
0x01b6 "ś" EEK_SYMBOL_CATEGORY_LETTER #                      sacute ś LATIN SMALL LETTER S WITH ACUTE 
 | 
			
		||||
0x01b7 "ˇ" EEK_SYMBOL_CATEGORY_LETTER #                       caron ˇ CARON 
 | 
			
		||||
0x01b9 "š" EEK_SYMBOL_CATEGORY_LETTER #                      scaron š LATIN SMALL LETTER S WITH CARON 
 | 
			
		||||
0x01ba "ş" EEK_SYMBOL_CATEGORY_LETTER #                    scedilla ş LATIN SMALL LETTER S WITH CEDILLA 
 | 
			
		||||
0x01bb "ť" EEK_SYMBOL_CATEGORY_LETTER #                      tcaron ť LATIN SMALL LETTER T WITH CARON 
 | 
			
		||||
0x01bc "ź" EEK_SYMBOL_CATEGORY_LETTER #                      zacute ź LATIN SMALL LETTER Z WITH ACUTE 
 | 
			
		||||
0x01bd "˝" EEK_SYMBOL_CATEGORY_LETTER #                 doubleacute ˝ DOUBLE ACUTE ACCENT 
 | 
			
		||||
0x01be "ž" EEK_SYMBOL_CATEGORY_LETTER #                      zcaron ž LATIN SMALL LETTER Z WITH CARON 
 | 
			
		||||
0x01bf "ż" EEK_SYMBOL_CATEGORY_LETTER #                   zabovedot ż LATIN SMALL LETTER Z WITH DOT ABOVE 
 | 
			
		||||
0x01c0 "Ŕ" EEK_SYMBOL_CATEGORY_LETTER #                      Racute Ŕ LATIN CAPITAL LETTER R WITH ACUTE 
 | 
			
		||||
0x01c3 "Ă" EEK_SYMBOL_CATEGORY_LETTER #                      Abreve Ă LATIN CAPITAL LETTER A WITH BREVE 
 | 
			
		||||
0x01c5 "Ĺ" EEK_SYMBOL_CATEGORY_LETTER #                      Lacute Ĺ LATIN CAPITAL LETTER L WITH ACUTE 
 | 
			
		||||
0x01c6 "Ć" EEK_SYMBOL_CATEGORY_LETTER #                      Cacute Ć LATIN CAPITAL LETTER C WITH ACUTE 
 | 
			
		||||
0x01c8 "Č" EEK_SYMBOL_CATEGORY_LETTER #                      Ccaron Č LATIN CAPITAL LETTER C WITH CARON 
 | 
			
		||||
0x01ca "Ę" EEK_SYMBOL_CATEGORY_LETTER #                     Eogonek Ę LATIN CAPITAL LETTER E WITH OGONEK 
 | 
			
		||||
0x01cc "Ě" EEK_SYMBOL_CATEGORY_LETTER #                      Ecaron Ě LATIN CAPITAL LETTER E WITH CARON 
 | 
			
		||||
0x01cf "Ď" EEK_SYMBOL_CATEGORY_LETTER #                      Dcaron Ď LATIN CAPITAL LETTER D WITH CARON 
 | 
			
		||||
0x01d0 "Đ" EEK_SYMBOL_CATEGORY_LETTER #                     Dstroke Đ LATIN CAPITAL LETTER D WITH STROKE 
 | 
			
		||||
0x01d1 "Ń" EEK_SYMBOL_CATEGORY_LETTER #                      Nacute Ń LATIN CAPITAL LETTER N WITH ACUTE 
 | 
			
		||||
0x01d2 "Ň" EEK_SYMBOL_CATEGORY_LETTER #                      Ncaron Ň LATIN CAPITAL LETTER N WITH CARON 
 | 
			
		||||
0x01d5 "Ő" EEK_SYMBOL_CATEGORY_LETTER #                Odoubleacute Ő LATIN CAPITAL LETTER O WITH DOUBLE ACUTE 
 | 
			
		||||
0x01d8 "Ř" EEK_SYMBOL_CATEGORY_LETTER #                      Rcaron Ř LATIN CAPITAL LETTER R WITH CARON 
 | 
			
		||||
0x01d9 "Ů" EEK_SYMBOL_CATEGORY_LETTER #                       Uring Ů LATIN CAPITAL LETTER U WITH RING ABOVE 
 | 
			
		||||
0x01db "Ű" EEK_SYMBOL_CATEGORY_LETTER #                Udoubleacute Ű LATIN CAPITAL LETTER U WITH DOUBLE ACUTE 
 | 
			
		||||
0x01de "Ţ" EEK_SYMBOL_CATEGORY_LETTER #                    Tcedilla Ţ LATIN CAPITAL LETTER T WITH CEDILLA 
 | 
			
		||||
0x01e0 "ŕ" EEK_SYMBOL_CATEGORY_LETTER #                      racute ŕ LATIN SMALL LETTER R WITH ACUTE 
 | 
			
		||||
0x01e3 "ă" EEK_SYMBOL_CATEGORY_LETTER #                      abreve ă LATIN SMALL LETTER A WITH BREVE 
 | 
			
		||||
0x01e5 "ĺ" EEK_SYMBOL_CATEGORY_LETTER #                      lacute ĺ LATIN SMALL LETTER L WITH ACUTE 
 | 
			
		||||
0x01e6 "ć" EEK_SYMBOL_CATEGORY_LETTER #                      cacute ć LATIN SMALL LETTER C WITH ACUTE 
 | 
			
		||||
0x01e8 "č" EEK_SYMBOL_CATEGORY_LETTER #                      ccaron č LATIN SMALL LETTER C WITH CARON 
 | 
			
		||||
0x01ea "ę" EEK_SYMBOL_CATEGORY_LETTER #                     eogonek ę LATIN SMALL LETTER E WITH OGONEK 
 | 
			
		||||
0x01ec "ě" EEK_SYMBOL_CATEGORY_LETTER #                      ecaron ě LATIN SMALL LETTER E WITH CARON 
 | 
			
		||||
0x01ef "ď" EEK_SYMBOL_CATEGORY_LETTER #                      dcaron ď LATIN SMALL LETTER D WITH CARON 
 | 
			
		||||
0x01f0 "đ" EEK_SYMBOL_CATEGORY_LETTER #                     dstroke đ LATIN SMALL LETTER D WITH STROKE 
 | 
			
		||||
0x01f1 "ń" EEK_SYMBOL_CATEGORY_LETTER #                      nacute ń LATIN SMALL LETTER N WITH ACUTE 
 | 
			
		||||
0x01f2 "ň" EEK_SYMBOL_CATEGORY_LETTER #                      ncaron ň LATIN SMALL LETTER N WITH CARON 
 | 
			
		||||
0x01f5 "ő" EEK_SYMBOL_CATEGORY_LETTER #                odoubleacute ő LATIN SMALL LETTER O WITH DOUBLE ACUTE 
 | 
			
		||||
0x01f8 "ř" EEK_SYMBOL_CATEGORY_LETTER #                      rcaron ř LATIN SMALL LETTER R WITH CARON 
 | 
			
		||||
0x01f9 "ů" EEK_SYMBOL_CATEGORY_LETTER #                       uring ů LATIN SMALL LETTER U WITH RING ABOVE 
 | 
			
		||||
0x01fb "ű" EEK_SYMBOL_CATEGORY_LETTER #                udoubleacute ű LATIN SMALL LETTER U WITH DOUBLE ACUTE 
 | 
			
		||||
0x01fe "ţ" EEK_SYMBOL_CATEGORY_LETTER #                    tcedilla ţ LATIN SMALL LETTER T WITH CEDILLA 
 | 
			
		||||
0x01ff "˙" EEK_SYMBOL_CATEGORY_LETTER #                    abovedot ˙ DOT ABOVE 
 | 
			
		||||
0x02a1 "Ħ" EEK_SYMBOL_CATEGORY_LETTER #                     Hstroke Ħ LATIN CAPITAL LETTER H WITH STROKE 
 | 
			
		||||
0x02a6 "Ĥ" EEK_SYMBOL_CATEGORY_LETTER #                 Hcircumflex Ĥ LATIN CAPITAL LETTER H WITH CIRCUMFLEX 
 | 
			
		||||
0x02a9 "İ" EEK_SYMBOL_CATEGORY_LETTER #                   Iabovedot İ LATIN CAPITAL LETTER I WITH DOT ABOVE 
 | 
			
		||||
0x02ab "Ğ" EEK_SYMBOL_CATEGORY_LETTER #                      Gbreve Ğ LATIN CAPITAL LETTER G WITH BREVE 
 | 
			
		||||
0x02ac "Ĵ" EEK_SYMBOL_CATEGORY_LETTER #                 Jcircumflex Ĵ LATIN CAPITAL LETTER J WITH CIRCUMFLEX 
 | 
			
		||||
0x02b1 "ħ" EEK_SYMBOL_CATEGORY_LETTER #                     hstroke ħ LATIN SMALL LETTER H WITH STROKE 
 | 
			
		||||
0x02b6 "ĥ" EEK_SYMBOL_CATEGORY_LETTER #                 hcircumflex ĥ LATIN SMALL LETTER H WITH CIRCUMFLEX 
 | 
			
		||||
0x02b9 "ı" EEK_SYMBOL_CATEGORY_LETTER #                    idotless ı LATIN SMALL LETTER DOTLESS I 
 | 
			
		||||
0x02bb "ğ" EEK_SYMBOL_CATEGORY_LETTER #                      gbreve ğ LATIN SMALL LETTER G WITH BREVE 
 | 
			
		||||
0x02bc "ĵ" EEK_SYMBOL_CATEGORY_LETTER #                 jcircumflex ĵ LATIN SMALL LETTER J WITH CIRCUMFLEX 
 | 
			
		||||
0x02c5 "Ċ" EEK_SYMBOL_CATEGORY_LETTER #                   Cabovedot Ċ LATIN CAPITAL LETTER C WITH DOT ABOVE 
 | 
			
		||||
0x02c6 "Ĉ" EEK_SYMBOL_CATEGORY_LETTER #                 Ccircumflex Ĉ LATIN CAPITAL LETTER C WITH CIRCUMFLEX 
 | 
			
		||||
0x02d5 "Ġ" EEK_SYMBOL_CATEGORY_LETTER #                   Gabovedot Ġ LATIN CAPITAL LETTER G WITH DOT ABOVE 
 | 
			
		||||
0x02d8 "Ĝ" EEK_SYMBOL_CATEGORY_LETTER #                 Gcircumflex Ĝ LATIN CAPITAL LETTER G WITH CIRCUMFLEX 
 | 
			
		||||
0x02dd "Ŭ" EEK_SYMBOL_CATEGORY_LETTER #                      Ubreve Ŭ LATIN CAPITAL LETTER U WITH BREVE 
 | 
			
		||||
0x02de "Ŝ" EEK_SYMBOL_CATEGORY_LETTER #                 Scircumflex Ŝ LATIN CAPITAL LETTER S WITH CIRCUMFLEX 
 | 
			
		||||
0x02e5 "ċ" EEK_SYMBOL_CATEGORY_LETTER #                   cabovedot ċ LATIN SMALL LETTER C WITH DOT ABOVE 
 | 
			
		||||
0x02e6 "ĉ" EEK_SYMBOL_CATEGORY_LETTER #                 ccircumflex ĉ LATIN SMALL LETTER C WITH CIRCUMFLEX 
 | 
			
		||||
0x02f5 "ġ" EEK_SYMBOL_CATEGORY_LETTER #                   gabovedot ġ LATIN SMALL LETTER G WITH DOT ABOVE 
 | 
			
		||||
0x02f8 "ĝ" EEK_SYMBOL_CATEGORY_LETTER #                 gcircumflex ĝ LATIN SMALL LETTER G WITH CIRCUMFLEX 
 | 
			
		||||
0x02fd "ŭ" EEK_SYMBOL_CATEGORY_LETTER #                      ubreve ŭ LATIN SMALL LETTER U WITH BREVE 
 | 
			
		||||
0x02fe "ŝ" EEK_SYMBOL_CATEGORY_LETTER #                 scircumflex ŝ LATIN SMALL LETTER S WITH CIRCUMFLEX 
 | 
			
		||||
0x03a2 "ĸ" EEK_SYMBOL_CATEGORY_LETTER #                         kra ĸ LATIN SMALL LETTER KRA 
 | 
			
		||||
0x03a3 "Ŗ" EEK_SYMBOL_CATEGORY_LETTER #                    Rcedilla Ŗ LATIN CAPITAL LETTER R WITH CEDILLA 
 | 
			
		||||
0x03a5 "Ĩ" EEK_SYMBOL_CATEGORY_LETTER #                      Itilde Ĩ LATIN CAPITAL LETTER I WITH TILDE 
 | 
			
		||||
0x03a6 "Ļ" EEK_SYMBOL_CATEGORY_LETTER #                    Lcedilla Ļ LATIN CAPITAL LETTER L WITH CEDILLA 
 | 
			
		||||
0x03aa "Ē" EEK_SYMBOL_CATEGORY_LETTER #                     Emacron Ē LATIN CAPITAL LETTER E WITH MACRON 
 | 
			
		||||
0x03ab "Ģ" EEK_SYMBOL_CATEGORY_LETTER #                    Gcedilla Ģ LATIN CAPITAL LETTER G WITH CEDILLA 
 | 
			
		||||
0x03ac "Ŧ" EEK_SYMBOL_CATEGORY_LETTER #                      Tslash Ŧ LATIN CAPITAL LETTER T WITH STROKE 
 | 
			
		||||
0x03b3 "ŗ" EEK_SYMBOL_CATEGORY_LETTER #                    rcedilla ŗ LATIN SMALL LETTER R WITH CEDILLA 
 | 
			
		||||
0x03b5 "ĩ" EEK_SYMBOL_CATEGORY_LETTER #                      itilde ĩ LATIN SMALL LETTER I WITH TILDE 
 | 
			
		||||
0x03b6 "ļ" EEK_SYMBOL_CATEGORY_LETTER #                    lcedilla ļ LATIN SMALL LETTER L WITH CEDILLA 
 | 
			
		||||
0x03ba "ē" EEK_SYMBOL_CATEGORY_LETTER #                     emacron ē LATIN SMALL LETTER E WITH MACRON 
 | 
			
		||||
0x03bb "ģ" EEK_SYMBOL_CATEGORY_LETTER #                    gcedilla ģ LATIN SMALL LETTER G WITH CEDILLA 
 | 
			
		||||
0x03bc "ŧ" EEK_SYMBOL_CATEGORY_LETTER #                      tslash ŧ LATIN SMALL LETTER T WITH STROKE 
 | 
			
		||||
0x03bd "Ŋ" EEK_SYMBOL_CATEGORY_LETTER #                         ENG Ŋ LATIN CAPITAL LETTER ENG 
 | 
			
		||||
0x03bf "ŋ" EEK_SYMBOL_CATEGORY_LETTER #                         eng ŋ LATIN SMALL LETTER ENG 
 | 
			
		||||
0x03c0 "Ā" EEK_SYMBOL_CATEGORY_LETTER #                     Amacron Ā LATIN CAPITAL LETTER A WITH MACRON 
 | 
			
		||||
0x03c7 "Į" EEK_SYMBOL_CATEGORY_LETTER #                     Iogonek Į LATIN CAPITAL LETTER I WITH OGONEK 
 | 
			
		||||
0x03cc "Ė" EEK_SYMBOL_CATEGORY_LETTER #                   Eabovedot Ė LATIN CAPITAL LETTER E WITH DOT ABOVE 
 | 
			
		||||
0x03cf "Ī" EEK_SYMBOL_CATEGORY_LETTER #                     Imacron Ī LATIN CAPITAL LETTER I WITH MACRON 
 | 
			
		||||
0x03d1 "Ņ" EEK_SYMBOL_CATEGORY_LETTER #                    Ncedilla Ņ LATIN CAPITAL LETTER N WITH CEDILLA 
 | 
			
		||||
0x03d2 "Ō" EEK_SYMBOL_CATEGORY_LETTER #                     Omacron Ō LATIN CAPITAL LETTER O WITH MACRON 
 | 
			
		||||
0x03d3 "Ķ" EEK_SYMBOL_CATEGORY_LETTER #                    Kcedilla Ķ LATIN CAPITAL LETTER K WITH CEDILLA 
 | 
			
		||||
0x03d9 "Ų" EEK_SYMBOL_CATEGORY_LETTER #                     Uogonek Ų LATIN CAPITAL LETTER U WITH OGONEK 
 | 
			
		||||
0x03dd "Ũ" EEK_SYMBOL_CATEGORY_LETTER #                      Utilde Ũ LATIN CAPITAL LETTER U WITH TILDE 
 | 
			
		||||
0x03de "Ū" EEK_SYMBOL_CATEGORY_LETTER #                     Umacron Ū LATIN CAPITAL LETTER U WITH MACRON 
 | 
			
		||||
0x03e0 "ā" EEK_SYMBOL_CATEGORY_LETTER #                     amacron ā LATIN SMALL LETTER A WITH MACRON 
 | 
			
		||||
0x03e7 "į" EEK_SYMBOL_CATEGORY_LETTER #                     iogonek į LATIN SMALL LETTER I WITH OGONEK 
 | 
			
		||||
0x03ec "ė" EEK_SYMBOL_CATEGORY_LETTER #                   eabovedot ė LATIN SMALL LETTER E WITH DOT ABOVE 
 | 
			
		||||
0x03ef "ī" EEK_SYMBOL_CATEGORY_LETTER #                     imacron ī LATIN SMALL LETTER I WITH MACRON 
 | 
			
		||||
0x03f1 "ņ" EEK_SYMBOL_CATEGORY_LETTER #                    ncedilla ņ LATIN SMALL LETTER N WITH CEDILLA 
 | 
			
		||||
0x03f2 "ō" EEK_SYMBOL_CATEGORY_LETTER #                     omacron ō LATIN SMALL LETTER O WITH MACRON 
 | 
			
		||||
0x03f3 "ķ" EEK_SYMBOL_CATEGORY_LETTER #                    kcedilla ķ LATIN SMALL LETTER K WITH CEDILLA 
 | 
			
		||||
0x03f9 "ų" EEK_SYMBOL_CATEGORY_LETTER #                     uogonek ų LATIN SMALL LETTER U WITH OGONEK 
 | 
			
		||||
0x03fd "ũ" EEK_SYMBOL_CATEGORY_LETTER #                      utilde ũ LATIN SMALL LETTER U WITH TILDE 
 | 
			
		||||
0x03fe "ū" EEK_SYMBOL_CATEGORY_LETTER #                     umacron ū LATIN SMALL LETTER U WITH MACRON 
 | 
			
		||||
0x047e "‾" EEK_SYMBOL_CATEGORY_LETTER #                    overline ‾ OVERLINE 
 | 
			
		||||
0x04a1 "。" EEK_SYMBOL_CATEGORY_LETTER #               kana_fullstop 。 IDEOGRAPHIC FULL STOP 
 | 
			
		||||
0x04a2 "「" EEK_SYMBOL_CATEGORY_LETTER #         kana_openingbracket 「 LEFT CORNER BRACKET 
 | 
			
		||||
0x04a3 "」" EEK_SYMBOL_CATEGORY_LETTER #         kana_closingbracket 」 RIGHT CORNER BRACKET 
 | 
			
		||||
0x04a4 "、" EEK_SYMBOL_CATEGORY_LETTER #                  kana_comma 、 IDEOGRAPHIC COMMA 
 | 
			
		||||
0x04a5 "・" EEK_SYMBOL_CATEGORY_LETTER #            kana_conjunctive ・ KATAKANA MIDDLE DOT 
 | 
			
		||||
0x04a6 "ヲ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_WO ヲ KATAKANA LETTER WO 
 | 
			
		||||
0x04a7 "ァ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_a ァ KATAKANA LETTER SMALL A 
 | 
			
		||||
0x04a8 "ィ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_i ィ KATAKANA LETTER SMALL I 
 | 
			
		||||
0x04a9 "ゥ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_u ゥ KATAKANA LETTER SMALL U 
 | 
			
		||||
0x04aa "ェ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_e ェ KATAKANA LETTER SMALL E 
 | 
			
		||||
0x04ab "ォ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_o ォ KATAKANA LETTER SMALL O 
 | 
			
		||||
0x04ac "ャ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_ya ャ KATAKANA LETTER SMALL YA 
 | 
			
		||||
0x04ad "ュ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_yu ュ KATAKANA LETTER SMALL YU 
 | 
			
		||||
0x04ae "ョ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_yo ョ KATAKANA LETTER SMALL YO 
 | 
			
		||||
0x04af "ッ" EEK_SYMBOL_CATEGORY_LETTER #                    kana_tsu ッ KATAKANA LETTER SMALL TU 
 | 
			
		||||
0x04b0 "ー" EEK_SYMBOL_CATEGORY_LETTER #              prolongedsound ー KATAKANA-HIRAGANA PROLONGED SOUND MARK 
 | 
			
		||||
0x04b1 "ア" EEK_SYMBOL_CATEGORY_LETTER #                      kana_A ア KATAKANA LETTER A 
 | 
			
		||||
0x04b2 "イ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_I イ KATAKANA LETTER I 
 | 
			
		||||
0x04b3 "ウ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_U ウ KATAKANA LETTER U 
 | 
			
		||||
0x04b4 "エ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_E エ KATAKANA LETTER E 
 | 
			
		||||
0x04b5 "オ" EEK_SYMBOL_CATEGORY_LETTER #                      kana_O オ KATAKANA LETTER O 
 | 
			
		||||
0x04b6 "カ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_KA カ KATAKANA LETTER KA 
 | 
			
		||||
0x04b7 "キ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_KI キ KATAKANA LETTER KI 
 | 
			
		||||
0x04b8 "ク" EEK_SYMBOL_CATEGORY_LETTER #                     kana_KU ク KATAKANA LETTER KU 
 | 
			
		||||
0x04b9 "ケ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_KE ケ KATAKANA LETTER KE 
 | 
			
		||||
0x04ba "コ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_KO コ KATAKANA LETTER KO 
 | 
			
		||||
0x04bb "サ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_SA サ KATAKANA LETTER SA 
 | 
			
		||||
0x04bc "シ" EEK_SYMBOL_CATEGORY_LETTER #                    kana_SHI シ KATAKANA LETTER SI 
 | 
			
		||||
0x04bd "ス" EEK_SYMBOL_CATEGORY_LETTER #                     kana_SU ス KATAKANA LETTER SU 
 | 
			
		||||
0x04be "セ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_SE セ KATAKANA LETTER SE 
 | 
			
		||||
0x04bf "ソ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_SO ソ KATAKANA LETTER SO 
 | 
			
		||||
0x04c0 "タ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_TA タ KATAKANA LETTER TA 
 | 
			
		||||
0x04c1 "チ" EEK_SYMBOL_CATEGORY_LETTER #                    kana_CHI チ KATAKANA LETTER TI 
 | 
			
		||||
0x04c2 "ツ" EEK_SYMBOL_CATEGORY_LETTER #                    kana_TSU ツ KATAKANA LETTER TU 
 | 
			
		||||
0x04c3 "テ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_TE テ KATAKANA LETTER TE 
 | 
			
		||||
0x04c4 "ト" EEK_SYMBOL_CATEGORY_LETTER #                     kana_TO ト KATAKANA LETTER TO 
 | 
			
		||||
0x04c5 "ナ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_NA ナ KATAKANA LETTER NA 
 | 
			
		||||
0x04c6 "ニ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_NI ニ KATAKANA LETTER NI 
 | 
			
		||||
0x04c7 "ヌ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_NU ヌ KATAKANA LETTER NU 
 | 
			
		||||
0x04c8 "ネ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_NE ネ KATAKANA LETTER NE 
 | 
			
		||||
0x04c9 "ノ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_NO ノ KATAKANA LETTER NO 
 | 
			
		||||
0x04ca "ハ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_HA ハ KATAKANA LETTER HA 
 | 
			
		||||
0x04cb "ヒ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_HI ヒ KATAKANA LETTER HI 
 | 
			
		||||
0x04cc "フ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_FU フ KATAKANA LETTER HU 
 | 
			
		||||
0x04cd "ヘ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_HE ヘ KATAKANA LETTER HE 
 | 
			
		||||
0x04ce "ホ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_HO ホ KATAKANA LETTER HO 
 | 
			
		||||
0x04cf "マ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_MA マ KATAKANA LETTER MA 
 | 
			
		||||
0x04d0 "ミ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_MI ミ KATAKANA LETTER MI 
 | 
			
		||||
0x04d1 "ム" EEK_SYMBOL_CATEGORY_LETTER #                     kana_MU ム KATAKANA LETTER MU 
 | 
			
		||||
0x04d2 "メ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_ME メ KATAKANA LETTER ME 
 | 
			
		||||
0x04d3 "モ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_MO モ KATAKANA LETTER MO 
 | 
			
		||||
0x04d4 "ヤ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_YA ヤ KATAKANA LETTER YA 
 | 
			
		||||
0x04d5 "ユ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_YU ユ KATAKANA LETTER YU 
 | 
			
		||||
0x04d6 "ヨ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_YO ヨ KATAKANA LETTER YO 
 | 
			
		||||
0x04d7 "ラ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_RA ラ KATAKANA LETTER RA 
 | 
			
		||||
0x04d8 "リ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_RI リ KATAKANA LETTER RI 
 | 
			
		||||
0x04d9 "ル" EEK_SYMBOL_CATEGORY_LETTER #                     kana_RU ル KATAKANA LETTER RU 
 | 
			
		||||
0x04da "レ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_RE レ KATAKANA LETTER RE 
 | 
			
		||||
0x04db "ロ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_RO ロ KATAKANA LETTER RO 
 | 
			
		||||
0x04dc "ワ" EEK_SYMBOL_CATEGORY_LETTER #                     kana_WA ワ KATAKANA LETTER WA 
 | 
			
		||||
0x04dd "ン" EEK_SYMBOL_CATEGORY_LETTER #                      kana_N ン KATAKANA LETTER N 
 | 
			
		||||
0x04de "゛" EEK_SYMBOL_CATEGORY_LETTER #                 voicedsound ゛ KATAKANA-HIRAGANA VOICED SOUND MARK 
 | 
			
		||||
0x04df "゜" EEK_SYMBOL_CATEGORY_LETTER #             semivoicedsound ゜ KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK 
 | 
			
		||||
0x05ac "،" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_comma ، ARABIC COMMA 
 | 
			
		||||
0x05bb "؛" EEK_SYMBOL_CATEGORY_LETTER #            Arabic_semicolon ؛ ARABIC SEMICOLON 
 | 
			
		||||
0x05bf "؟" EEK_SYMBOL_CATEGORY_LETTER #        Arabic_question_mark ؟ ARABIC QUESTION MARK 
 | 
			
		||||
0x05c1 "ء" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_hamza ء ARABIC LETTER HAMZA 
 | 
			
		||||
0x05c2 "آ" EEK_SYMBOL_CATEGORY_LETTER #          Arabic_maddaonalef آ ARABIC LETTER ALEF WITH MADDA ABOVE 
 | 
			
		||||
0x05c3 "أ" EEK_SYMBOL_CATEGORY_LETTER #          Arabic_hamzaonalef أ ARABIC LETTER ALEF WITH HAMZA ABOVE 
 | 
			
		||||
0x05c4 "ؤ" EEK_SYMBOL_CATEGORY_LETTER #           Arabic_hamzaonwaw ؤ ARABIC LETTER WAW WITH HAMZA ABOVE 
 | 
			
		||||
0x05c5 "إ" EEK_SYMBOL_CATEGORY_LETTER #       Arabic_hamzaunderalef إ ARABIC LETTER ALEF WITH HAMZA BELOW 
 | 
			
		||||
0x05c6 "ئ" EEK_SYMBOL_CATEGORY_LETTER #           Arabic_hamzaonyeh ئ ARABIC LETTER YEH WITH HAMZA ABOVE 
 | 
			
		||||
0x05c7 "ا" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_alef ا ARABIC LETTER ALEF 
 | 
			
		||||
0x05c8 "ب" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_beh ب ARABIC LETTER BEH 
 | 
			
		||||
0x05c9 "ة" EEK_SYMBOL_CATEGORY_LETTER #           Arabic_tehmarbuta ة ARABIC LETTER TEH MARBUTA 
 | 
			
		||||
0x05ca "ت" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_teh ت ARABIC LETTER TEH 
 | 
			
		||||
0x05cb "ث" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_theh ث ARABIC LETTER THEH 
 | 
			
		||||
0x05cc "ج" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_jeem ج ARABIC LETTER JEEM 
 | 
			
		||||
0x05cd "ح" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_hah ح ARABIC LETTER HAH 
 | 
			
		||||
0x05ce "خ" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_khah خ ARABIC LETTER KHAH 
 | 
			
		||||
0x05cf "د" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_dal د ARABIC LETTER DAL 
 | 
			
		||||
0x05d0 "ذ" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_thal ذ ARABIC LETTER THAL 
 | 
			
		||||
0x05d1 "ر" EEK_SYMBOL_CATEGORY_LETTER #                   Arabic_ra ر ARABIC LETTER REH 
 | 
			
		||||
0x05d2 "ز" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_zain ز ARABIC LETTER ZAIN 
 | 
			
		||||
0x05d3 "س" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_seen س ARABIC LETTER SEEN 
 | 
			
		||||
0x05d4 "ش" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_sheen ش ARABIC LETTER SHEEN 
 | 
			
		||||
0x05d5 "ص" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_sad ص ARABIC LETTER SAD 
 | 
			
		||||
0x05d6 "ض" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_dad ض ARABIC LETTER DAD 
 | 
			
		||||
0x05d7 "ط" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_tah ط ARABIC LETTER TAH 
 | 
			
		||||
0x05d8 "ظ" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_zah ظ ARABIC LETTER ZAH 
 | 
			
		||||
0x05d9 "ع" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_ain ع ARABIC LETTER AIN 
 | 
			
		||||
0x05da "غ" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_ghain غ ARABIC LETTER GHAIN 
 | 
			
		||||
0x05e0 "ـ" EEK_SYMBOL_CATEGORY_LETTER #              Arabic_tatweel ـ ARABIC TATWEEL 
 | 
			
		||||
0x05e1 "ف" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_feh ف ARABIC LETTER FEH 
 | 
			
		||||
0x05e2 "ق" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_qaf ق ARABIC LETTER QAF 
 | 
			
		||||
0x05e3 "ك" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_kaf ك ARABIC LETTER KAF 
 | 
			
		||||
0x05e4 "ل" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_lam ل ARABIC LETTER LAM 
 | 
			
		||||
0x05e5 "م" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_meem م ARABIC LETTER MEEM 
 | 
			
		||||
0x05e6 "ن" EEK_SYMBOL_CATEGORY_LETTER #                 Arabic_noon ن ARABIC LETTER NOON 
 | 
			
		||||
0x05e7 "ه" EEK_SYMBOL_CATEGORY_LETTER #                   Arabic_ha ه ARABIC LETTER HEH 
 | 
			
		||||
0x05e8 "و" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_waw و ARABIC LETTER WAW 
 | 
			
		||||
0x05e9 "ى" EEK_SYMBOL_CATEGORY_LETTER #          Arabic_alefmaksura ى ARABIC LETTER ALEF MAKSURA 
 | 
			
		||||
0x05ea "ي" EEK_SYMBOL_CATEGORY_LETTER #                  Arabic_yeh ي ARABIC LETTER YEH 
 | 
			
		||||
0x05eb "ً" EEK_SYMBOL_CATEGORY_LETTER #             Arabic_fathatan ً ARABIC FATHATAN 
 | 
			
		||||
0x05ec "ٌ" EEK_SYMBOL_CATEGORY_LETTER #             Arabic_dammatan ٌ ARABIC DAMMATAN 
 | 
			
		||||
0x05ed "ٍ" EEK_SYMBOL_CATEGORY_LETTER #             Arabic_kasratan ٍ ARABIC KASRATAN 
 | 
			
		||||
0x05ee "َ" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_fatha َ ARABIC FATHA 
 | 
			
		||||
0x05ef "ُ" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_damma ُ ARABIC DAMMA 
 | 
			
		||||
0x05f0 "ِ" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_kasra ِ ARABIC KASRA 
 | 
			
		||||
0x05f1 "ّ" EEK_SYMBOL_CATEGORY_LETTER #               Arabic_shadda ّ ARABIC SHADDA 
 | 
			
		||||
0x05f2 "ْ" EEK_SYMBOL_CATEGORY_LETTER #                Arabic_sukun ْ ARABIC SUKUN 
 | 
			
		||||
0x06a1 "ђ" EEK_SYMBOL_CATEGORY_LETTER #                 Serbian_dje ђ CYRILLIC SMALL LETTER DJE 
 | 
			
		||||
0x06a2 "ѓ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_gje ѓ CYRILLIC SMALL LETTER GJE 
 | 
			
		||||
0x06a3 "ё" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_io ё CYRILLIC SMALL LETTER IO 
 | 
			
		||||
0x06a4 "є" EEK_SYMBOL_CATEGORY_LETTER #                Ukrainian_ie є CYRILLIC SMALL LETTER UKRAINIAN IE 
 | 
			
		||||
0x06a5 "ѕ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_dse ѕ CYRILLIC SMALL LETTER DZE 
 | 
			
		||||
0x06a6 "і" EEK_SYMBOL_CATEGORY_LETTER #                 Ukrainian_i і CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I 
 | 
			
		||||
0x06a7 "ї" EEK_SYMBOL_CATEGORY_LETTER #                Ukrainian_yi ї CYRILLIC SMALL LETTER YI 
 | 
			
		||||
0x06a8 "ј" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_je ј CYRILLIC SMALL LETTER JE 
 | 
			
		||||
0x06a9 "љ" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_lje љ CYRILLIC SMALL LETTER LJE 
 | 
			
		||||
0x06aa "њ" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_nje њ CYRILLIC SMALL LETTER NJE 
 | 
			
		||||
0x06ab "ћ" EEK_SYMBOL_CATEGORY_LETTER #                Serbian_tshe ћ CYRILLIC SMALL LETTER TSHE 
 | 
			
		||||
0x06ac "ќ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_kje ќ CYRILLIC SMALL LETTER KJE 
 | 
			
		||||
0x06ad "ґ" EEK_SYMBOL_CATEGORY_LETTER #   Ukrainian_ghe_with_upturn ґ CYRILLIC SMALL LETTER GHE WITH UPTURN 
 | 
			
		||||
0x06ae "ў" EEK_SYMBOL_CATEGORY_LETTER #         Byelorussian_shortu ў CYRILLIC SMALL LETTER SHORT U 
 | 
			
		||||
0x06af "џ" EEK_SYMBOL_CATEGORY_LETTER #               Cyrillic_dzhe џ CYRILLIC SMALL LETTER DZHE 
 | 
			
		||||
0x06b0 "№" EEK_SYMBOL_CATEGORY_LETTER #                  numerosign № NUMERO SIGN 
 | 
			
		||||
0x06b1 "Ђ" EEK_SYMBOL_CATEGORY_LETTER #                 Serbian_DJE Ђ CYRILLIC CAPITAL LETTER DJE 
 | 
			
		||||
0x06b2 "Ѓ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_GJE Ѓ CYRILLIC CAPITAL LETTER GJE 
 | 
			
		||||
0x06b3 "Ё" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_IO Ё CYRILLIC CAPITAL LETTER IO 
 | 
			
		||||
0x06b4 "Є" EEK_SYMBOL_CATEGORY_LETTER #                Ukrainian_IE Є CYRILLIC CAPITAL LETTER UKRAINIAN IE 
 | 
			
		||||
0x06b5 "Ѕ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_DSE Ѕ CYRILLIC CAPITAL LETTER DZE 
 | 
			
		||||
0x06b6 "І" EEK_SYMBOL_CATEGORY_LETTER #                 Ukrainian_I І CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I 
 | 
			
		||||
0x06b7 "Ї" EEK_SYMBOL_CATEGORY_LETTER #                Ukrainian_YI Ї CYRILLIC CAPITAL LETTER YI 
 | 
			
		||||
0x06b8 "Ј" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_JE Ј CYRILLIC CAPITAL LETTER JE 
 | 
			
		||||
0x06b9 "Љ" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_LJE Љ CYRILLIC CAPITAL LETTER LJE 
 | 
			
		||||
0x06ba "Њ" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_NJE Њ CYRILLIC CAPITAL LETTER NJE 
 | 
			
		||||
0x06bb "Ћ" EEK_SYMBOL_CATEGORY_LETTER #                Serbian_TSHE Ћ CYRILLIC CAPITAL LETTER TSHE 
 | 
			
		||||
0x06bc "Ќ" EEK_SYMBOL_CATEGORY_LETTER #               Macedonia_KJE Ќ CYRILLIC CAPITAL LETTER KJE 
 | 
			
		||||
0x06bd "Ґ" EEK_SYMBOL_CATEGORY_LETTER #   Ukrainian_GHE_WITH_UPTURN Ґ CYRILLIC CAPITAL LETTER GHE WITH UPTURN 
 | 
			
		||||
0x06be "Ў" EEK_SYMBOL_CATEGORY_LETTER #         Byelorussian_SHORTU Ў CYRILLIC CAPITAL LETTER SHORT U 
 | 
			
		||||
0x06bf "Џ" EEK_SYMBOL_CATEGORY_LETTER #               Cyrillic_DZHE Џ CYRILLIC CAPITAL LETTER DZHE 
 | 
			
		||||
0x06c0 "ю" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_yu ю CYRILLIC SMALL LETTER YU 
 | 
			
		||||
0x06c1 "а" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_a а CYRILLIC SMALL LETTER A 
 | 
			
		||||
0x06c2 "б" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_be б CYRILLIC SMALL LETTER BE 
 | 
			
		||||
0x06c3 "ц" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_tse ц CYRILLIC SMALL LETTER TSE 
 | 
			
		||||
0x06c4 "д" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_de д CYRILLIC SMALL LETTER DE 
 | 
			
		||||
0x06c5 "е" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ie е CYRILLIC SMALL LETTER IE 
 | 
			
		||||
0x06c6 "ф" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ef ф CYRILLIC SMALL LETTER EF 
 | 
			
		||||
0x06c7 "г" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_ghe г CYRILLIC SMALL LETTER GHE 
 | 
			
		||||
0x06c8 "х" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ha х CYRILLIC SMALL LETTER HA 
 | 
			
		||||
0x06c9 "и" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_i и CYRILLIC SMALL LETTER I 
 | 
			
		||||
0x06ca "й" EEK_SYMBOL_CATEGORY_LETTER #             Cyrillic_shorti й CYRILLIC SMALL LETTER SHORT I 
 | 
			
		||||
0x06cb "к" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ka к CYRILLIC SMALL LETTER KA 
 | 
			
		||||
0x06cc "л" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_el л CYRILLIC SMALL LETTER EL 
 | 
			
		||||
0x06cd "м" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_em м CYRILLIC SMALL LETTER EM 
 | 
			
		||||
0x06ce "н" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_en н CYRILLIC SMALL LETTER EN 
 | 
			
		||||
0x06cf "о" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_o о CYRILLIC SMALL LETTER O 
 | 
			
		||||
0x06d0 "п" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_pe п CYRILLIC SMALL LETTER PE 
 | 
			
		||||
0x06d1 "я" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ya я CYRILLIC SMALL LETTER YA 
 | 
			
		||||
0x06d2 "р" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_er р CYRILLIC SMALL LETTER ER 
 | 
			
		||||
0x06d3 "с" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_es с CYRILLIC SMALL LETTER ES 
 | 
			
		||||
0x06d4 "т" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_te т CYRILLIC SMALL LETTER TE 
 | 
			
		||||
0x06d5 "у" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_u у CYRILLIC SMALL LETTER U 
 | 
			
		||||
0x06d6 "ж" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_zhe ж CYRILLIC SMALL LETTER ZHE 
 | 
			
		||||
0x06d7 "в" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ve в CYRILLIC SMALL LETTER VE 
 | 
			
		||||
0x06d8 "ь" EEK_SYMBOL_CATEGORY_LETTER #           Cyrillic_softsign ь CYRILLIC SMALL LETTER SOFT SIGN 
 | 
			
		||||
0x06d9 "ы" EEK_SYMBOL_CATEGORY_LETTER #               Cyrillic_yeru ы CYRILLIC SMALL LETTER YERU 
 | 
			
		||||
0x06da "з" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ze з CYRILLIC SMALL LETTER ZE 
 | 
			
		||||
0x06db "ш" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_sha ш CYRILLIC SMALL LETTER SHA 
 | 
			
		||||
0x06dc "э" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_e э CYRILLIC SMALL LETTER E 
 | 
			
		||||
0x06dd "щ" EEK_SYMBOL_CATEGORY_LETTER #              Cyrillic_shcha щ CYRILLIC SMALL LETTER SHCHA 
 | 
			
		||||
0x06de "ч" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_che ч CYRILLIC SMALL LETTER CHE 
 | 
			
		||||
0x06df "ъ" EEK_SYMBOL_CATEGORY_LETTER #           Cyrillic_hardsign ъ CYRILLIC SMALL LETTER HARD SIGN 
 | 
			
		||||
0x06e0 "Ю" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_YU Ю CYRILLIC CAPITAL LETTER YU 
 | 
			
		||||
0x06e1 "А" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_A А CYRILLIC CAPITAL LETTER A 
 | 
			
		||||
0x06e2 "Б" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_BE Б CYRILLIC CAPITAL LETTER BE 
 | 
			
		||||
0x06e3 "Ц" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_TSE Ц CYRILLIC CAPITAL LETTER TSE 
 | 
			
		||||
0x06e4 "Д" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_DE Д CYRILLIC CAPITAL LETTER DE 
 | 
			
		||||
0x06e5 "Е" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_IE Е CYRILLIC CAPITAL LETTER IE 
 | 
			
		||||
0x06e6 "Ф" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_EF Ф CYRILLIC CAPITAL LETTER EF 
 | 
			
		||||
0x06e7 "Г" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_GHE Г CYRILLIC CAPITAL LETTER GHE 
 | 
			
		||||
0x06e8 "Х" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_HA Х CYRILLIC CAPITAL LETTER HA 
 | 
			
		||||
0x06e9 "И" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_I И CYRILLIC CAPITAL LETTER I 
 | 
			
		||||
0x06ea "Й" EEK_SYMBOL_CATEGORY_LETTER #             Cyrillic_SHORTI Й CYRILLIC CAPITAL LETTER SHORT I 
 | 
			
		||||
0x06eb "К" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_KA К CYRILLIC CAPITAL LETTER KA 
 | 
			
		||||
0x06ec "Л" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_EL Л CYRILLIC CAPITAL LETTER EL 
 | 
			
		||||
0x06ed "М" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_EM М CYRILLIC CAPITAL LETTER EM 
 | 
			
		||||
0x06ee "Н" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_EN Н CYRILLIC CAPITAL LETTER EN 
 | 
			
		||||
0x06ef "О" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_O О CYRILLIC CAPITAL LETTER O 
 | 
			
		||||
0x06f0 "П" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_PE П CYRILLIC CAPITAL LETTER PE 
 | 
			
		||||
0x06f1 "Я" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_YA Я CYRILLIC CAPITAL LETTER YA 
 | 
			
		||||
0x06f2 "Р" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ER Р CYRILLIC CAPITAL LETTER ER 
 | 
			
		||||
0x06f3 "С" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ES С CYRILLIC CAPITAL LETTER ES 
 | 
			
		||||
0x06f4 "Т" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_TE Т CYRILLIC CAPITAL LETTER TE 
 | 
			
		||||
0x06f5 "У" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_U У CYRILLIC CAPITAL LETTER U 
 | 
			
		||||
0x06f6 "Ж" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_ZHE Ж CYRILLIC CAPITAL LETTER ZHE 
 | 
			
		||||
0x06f7 "В" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_VE В CYRILLIC CAPITAL LETTER VE 
 | 
			
		||||
0x06f8 "Ь" EEK_SYMBOL_CATEGORY_LETTER #           Cyrillic_SOFTSIGN Ь CYRILLIC CAPITAL LETTER SOFT SIGN 
 | 
			
		||||
0x06f9 "Ы" EEK_SYMBOL_CATEGORY_LETTER #               Cyrillic_YERU Ы CYRILLIC CAPITAL LETTER YERU 
 | 
			
		||||
0x06fa "З" EEK_SYMBOL_CATEGORY_LETTER #                 Cyrillic_ZE З CYRILLIC CAPITAL LETTER ZE 
 | 
			
		||||
0x06fb "Ш" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_SHA Ш CYRILLIC CAPITAL LETTER SHA 
 | 
			
		||||
0x06fc "Э" EEK_SYMBOL_CATEGORY_LETTER #                  Cyrillic_E Э CYRILLIC CAPITAL LETTER E 
 | 
			
		||||
0x06fd "Щ" EEK_SYMBOL_CATEGORY_LETTER #              Cyrillic_SHCHA Щ CYRILLIC CAPITAL LETTER SHCHA 
 | 
			
		||||
0x06fe "Ч" EEK_SYMBOL_CATEGORY_LETTER #                Cyrillic_CHE Ч CYRILLIC CAPITAL LETTER CHE 
 | 
			
		||||
0x06ff "Ъ" EEK_SYMBOL_CATEGORY_LETTER #           Cyrillic_HARDSIGN Ъ CYRILLIC CAPITAL LETTER HARD SIGN 
 | 
			
		||||
0x07a1 "Ά" EEK_SYMBOL_CATEGORY_LETTER #           Geek_ALPHAaccent Ά GREEK CAPITAL LETTER ALPHA WITH TONOS 
 | 
			
		||||
0x07a2 "Έ" EEK_SYMBOL_CATEGORY_LETTER #         Geek_EPSILONaccent Έ GREEK CAPITAL LETTER EPSILON WITH TONOS 
 | 
			
		||||
0x07a3 "Ή" EEK_SYMBOL_CATEGORY_LETTER #             Geek_ETAaccent Ή GREEK CAPITAL LETTER ETA WITH TONOS 
 | 
			
		||||
0x07a4 "Ί" EEK_SYMBOL_CATEGORY_LETTER #            Geek_IOTAaccent Ί GREEK CAPITAL LETTER IOTA WITH TONOS 
 | 
			
		||||
0x07a5 "Ϊ" EEK_SYMBOL_CATEGORY_LETTER #          Geek_IOTAdieresis Ϊ GREEK CAPITAL LETTER IOTA WITH DIALYTIKA 
 | 
			
		||||
0x07a7 "Ό" EEK_SYMBOL_CATEGORY_LETTER #         Geek_OMICRONaccent Ό GREEK CAPITAL LETTER OMICRON WITH TONOS 
 | 
			
		||||
0x07a8 "Ύ" EEK_SYMBOL_CATEGORY_LETTER #         Geek_UPSILONaccent Ύ GREEK CAPITAL LETTER UPSILON WITH TONOS 
 | 
			
		||||
0x07a9 "Ϋ" EEK_SYMBOL_CATEGORY_LETTER #       Geek_UPSILONdieresis Ϋ GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA 
 | 
			
		||||
0x07ab "Ώ" EEK_SYMBOL_CATEGORY_LETTER #           Geek_OMEGAaccent Ώ GREEK CAPITAL LETTER OMEGA WITH TONOS 
 | 
			
		||||
0x07ae "΅" EEK_SYMBOL_CATEGORY_LETTER #        Geek_accentdieresis ΅ GREEK DIALYTIKA TONOS 
 | 
			
		||||
0x07af "―" EEK_SYMBOL_CATEGORY_LETTER #              Geek_horizbar ― HORIZONTAL BAR 
 | 
			
		||||
0x07b1 "ά" EEK_SYMBOL_CATEGORY_LETTER #           Geek_alphaaccent ά GREEK SMALL LETTER ALPHA WITH TONOS 
 | 
			
		||||
0x07b2 "έ" EEK_SYMBOL_CATEGORY_LETTER #         Geek_epsilonaccent έ GREEK SMALL LETTER EPSILON WITH TONOS 
 | 
			
		||||
0x07b3 "ή" EEK_SYMBOL_CATEGORY_LETTER #             Geek_etaaccent ή GREEK SMALL LETTER ETA WITH TONOS 
 | 
			
		||||
0x07b4 "ί" EEK_SYMBOL_CATEGORY_LETTER #            Geek_iotaaccent ί GREEK SMALL LETTER IOTA WITH TONOS 
 | 
			
		||||
0x07b5 "ϊ" EEK_SYMBOL_CATEGORY_LETTER #          Geek_iotadieresis ϊ GREEK SMALL LETTER IOTA WITH DIALYTIKA 
 | 
			
		||||
0x07b6 "ΐ" EEK_SYMBOL_CATEGORY_LETTER #    Geek_iotaaccentdieresis ΐ GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS 
 | 
			
		||||
0x07b7 "ό" EEK_SYMBOL_CATEGORY_LETTER #         Geek_omicronaccent ό GREEK SMALL LETTER OMICRON WITH TONOS 
 | 
			
		||||
0x07b8 "ύ" EEK_SYMBOL_CATEGORY_LETTER #         Geek_upsilonaccent ύ GREEK SMALL LETTER UPSILON WITH TONOS 
 | 
			
		||||
0x07b9 "ϋ" EEK_SYMBOL_CATEGORY_LETTER #       Geek_upsilondieresis ϋ GREEK SMALL LETTER UPSILON WITH DIALYTIKA 
 | 
			
		||||
0x07ba "ΰ" EEK_SYMBOL_CATEGORY_LETTER # Geek_upsilonaccentdieresis ΰ GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS 
 | 
			
		||||
0x07bb "ώ" EEK_SYMBOL_CATEGORY_LETTER #           Geek_omegaaccent ώ GREEK SMALL LETTER OMEGA WITH TONOS 
 | 
			
		||||
0x07c1 "Α" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_ALPHA Α GREEK CAPITAL LETTER ALPHA 
 | 
			
		||||
0x07c2 "Β" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_BETA Β GREEK CAPITAL LETTER BETA 
 | 
			
		||||
0x07c3 "Γ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_GAMMA Γ GREEK CAPITAL LETTER GAMMA 
 | 
			
		||||
0x07c4 "Δ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_DELTA Δ GREEK CAPITAL LETTER DELTA 
 | 
			
		||||
0x07c5 "Ε" EEK_SYMBOL_CATEGORY_LETTER #               Geek_EPSILON Ε GREEK CAPITAL LETTER EPSILON 
 | 
			
		||||
0x07c6 "Ζ" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_ZETA Ζ GREEK CAPITAL LETTER ZETA 
 | 
			
		||||
0x07c7 "Η" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_ETA Η GREEK CAPITAL LETTER ETA 
 | 
			
		||||
0x07c8 "Θ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_THETA Θ GREEK CAPITAL LETTER THETA 
 | 
			
		||||
0x07c9 "Ι" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_IOTA Ι GREEK CAPITAL LETTER IOTA 
 | 
			
		||||
0x07ca "Κ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_KAPPA Κ GREEK CAPITAL LETTER KAPPA 
 | 
			
		||||
0x07cb "Λ" EEK_SYMBOL_CATEGORY_LETTER #                Geek_LAMBDA Λ GREEK CAPITAL LETTER LAMDA 
 | 
			
		||||
0x07cc "Μ" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_MU Μ GREEK CAPITAL LETTER MU 
 | 
			
		||||
0x07cd "Ν" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_NU Ν GREEK CAPITAL LETTER NU 
 | 
			
		||||
0x07ce "Ξ" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_XI Ξ GREEK CAPITAL LETTER XI 
 | 
			
		||||
0x07cf "Ο" EEK_SYMBOL_CATEGORY_LETTER #               Geek_OMICRON Ο GREEK CAPITAL LETTER OMICRON 
 | 
			
		||||
0x07d0 "Π" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_PI Π GREEK CAPITAL LETTER PI 
 | 
			
		||||
0x07d1 "Ρ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_RHO Ρ GREEK CAPITAL LETTER RHO 
 | 
			
		||||
0x07d2 "Σ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_SIGMA Σ GREEK CAPITAL LETTER SIGMA 
 | 
			
		||||
0x07d4 "Τ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_TAU Τ GREEK CAPITAL LETTER TAU 
 | 
			
		||||
0x07d5 "Υ" EEK_SYMBOL_CATEGORY_LETTER #               Geek_UPSILON Υ GREEK CAPITAL LETTER UPSILON 
 | 
			
		||||
0x07d6 "Φ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_PHI Φ GREEK CAPITAL LETTER PHI 
 | 
			
		||||
0x07d7 "Χ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_CHI Χ GREEK CAPITAL LETTER CHI 
 | 
			
		||||
0x07d8 "Ψ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_PSI Ψ GREEK CAPITAL LETTER PSI 
 | 
			
		||||
0x07d9 "Ω" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_OMEGA Ω GREEK CAPITAL LETTER OMEGA 
 | 
			
		||||
0x07e1 "α" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_alpha α GREEK SMALL LETTER ALPHA 
 | 
			
		||||
0x07e2 "β" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_beta β GREEK SMALL LETTER BETA 
 | 
			
		||||
0x07e3 "γ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_gamma γ GREEK SMALL LETTER GAMMA 
 | 
			
		||||
0x07e4 "δ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_delta δ GREEK SMALL LETTER DELTA 
 | 
			
		||||
0x07e5 "ε" EEK_SYMBOL_CATEGORY_LETTER #               Geek_epsilon ε GREEK SMALL LETTER EPSILON 
 | 
			
		||||
0x07e6 "ζ" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_zeta ζ GREEK SMALL LETTER ZETA 
 | 
			
		||||
0x07e7 "η" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_eta η GREEK SMALL LETTER ETA 
 | 
			
		||||
0x07e8 "θ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_theta θ GREEK SMALL LETTER THETA 
 | 
			
		||||
0x07e9 "ι" EEK_SYMBOL_CATEGORY_LETTER #                  Geek_iota ι GREEK SMALL LETTER IOTA 
 | 
			
		||||
0x07ea "κ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_kappa κ GREEK SMALL LETTER KAPPA 
 | 
			
		||||
0x07eb "λ" EEK_SYMBOL_CATEGORY_LETTER #                Geek_lambda λ GREEK SMALL LETTER LAMDA 
 | 
			
		||||
0x07ec "μ" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_mu μ GREEK SMALL LETTER MU 
 | 
			
		||||
0x07ed "ν" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_nu ν GREEK SMALL LETTER NU 
 | 
			
		||||
0x07ee "ξ" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_xi ξ GREEK SMALL LETTER XI 
 | 
			
		||||
0x07ef "ο" EEK_SYMBOL_CATEGORY_LETTER #               Geek_omicron ο GREEK SMALL LETTER OMICRON 
 | 
			
		||||
0x07f0 "π" EEK_SYMBOL_CATEGORY_LETTER #                    Geek_pi π GREEK SMALL LETTER PI 
 | 
			
		||||
0x07f1 "ρ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_rho ρ GREEK SMALL LETTER RHO 
 | 
			
		||||
0x07f2 "σ" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_sigma σ GREEK SMALL LETTER SIGMA 
 | 
			
		||||
0x07f3 "ς" EEK_SYMBOL_CATEGORY_LETTER #       Geek_finalsmallsigma ς GREEK SMALL LETTER FINAL SIGMA 
 | 
			
		||||
0x07f4 "τ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_tau τ GREEK SMALL LETTER TAU 
 | 
			
		||||
0x07f5 "υ" EEK_SYMBOL_CATEGORY_LETTER #               Geek_upsilon υ GREEK SMALL LETTER UPSILON 
 | 
			
		||||
0x07f6 "φ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_phi φ GREEK SMALL LETTER PHI 
 | 
			
		||||
0x07f7 "χ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_chi χ GREEK SMALL LETTER CHI 
 | 
			
		||||
0x07f8 "ψ" EEK_SYMBOL_CATEGORY_LETTER #                   Geek_psi ψ GREEK SMALL LETTER PSI 
 | 
			
		||||
0x07f9 "ω" EEK_SYMBOL_CATEGORY_LETTER #                 Geek_omega ω GREEK SMALL LETTER OMEGA 
 | 
			
		||||
#   0x08a1                               leftradical ? ??? 
 | 
			
		||||
#   0x08a2                            topleftradical ? ??? 
 | 
			
		||||
#   0x08a3                            horizconnector ? ??? 
 | 
			
		||||
0x08a4 "⌠" EEK_SYMBOL_CATEGORY_LETTER #                 topintegral ⌠ TOP HALF INTEGRAL 
 | 
			
		||||
0x08a5 "⌡" EEK_SYMBOL_CATEGORY_LETTER #                 botintegral ⌡ BOTTOM HALF INTEGRAL 
 | 
			
		||||
0x08a6 "│" EEK_SYMBOL_CATEGORY_LETTER #               vertconnector │ BOX DRAWINGS LIGHT VERTICAL 
 | 
			
		||||
#   0x08a7                          topleftsqbracket ? ??? 
 | 
			
		||||
#   0x08a8                          botleftsqbracket ? ??? 
 | 
			
		||||
#   0x08a9                         toprightsqbracket ? ??? 
 | 
			
		||||
#   0x08aa                         botrightsqbracket ? ??? 
 | 
			
		||||
#   0x08ab                             topleftparens ? ??? 
 | 
			
		||||
#   0x08ac                             botleftparens ? ??? 
 | 
			
		||||
#   0x08ad                            toprightparens ? ??? 
 | 
			
		||||
#   0x08ae                            botrightparens ? ??? 
 | 
			
		||||
#   0x08af                      leftmiddlecurlybrace ? ??? 
 | 
			
		||||
#   0x08b0                     rightmiddlecurlybrace ? ??? 
 | 
			
		||||
#   0x08b1                          topleftsummation ? ??? 
 | 
			
		||||
#   0x08b2                          botleftsummation ? ??? 
 | 
			
		||||
#   0x08b3                 topvertsummationconnector ? ??? 
 | 
			
		||||
#   0x08b4                 botvertsummationconnector ? ??? 
 | 
			
		||||
#   0x08b5                         toprightsummation ? ??? 
 | 
			
		||||
#   0x08b6                         botrightsummation ? ??? 
 | 
			
		||||
#   0x08b7                      rightmiddlesummation ? ??? 
 | 
			
		||||
0x08bc "≤" EEK_SYMBOL_CATEGORY_LETTER #               lessthanequal ≤ LESS-THAN OR EQUAL TO 
 | 
			
		||||
0x08bd "≠" EEK_SYMBOL_CATEGORY_LETTER #                    notequal ≠ NOT EQUAL TO 
 | 
			
		||||
0x08be "≥" EEK_SYMBOL_CATEGORY_LETTER #            greaterthanequal ≥ GREATER-THAN OR EQUAL TO 
 | 
			
		||||
0x08bf "∫" EEK_SYMBOL_CATEGORY_LETTER #                    integral ∫ INTEGRAL 
 | 
			
		||||
0x08c0 "∴" EEK_SYMBOL_CATEGORY_LETTER #                   therefore ∴ THEREFORE 
 | 
			
		||||
0x08c1 "∝" EEK_SYMBOL_CATEGORY_LETTER #                   variation ∝ PROPORTIONAL TO 
 | 
			
		||||
0x08c2 "∞" EEK_SYMBOL_CATEGORY_LETTER #                    infinity ∞ INFINITY 
 | 
			
		||||
0x08c5 "∇" EEK_SYMBOL_CATEGORY_LETTER #                       nabla ∇ NABLA 
 | 
			
		||||
0x08c8 "≅" EEK_SYMBOL_CATEGORY_LETTER #                 approximate ≅ APPROXIMATELY EQUAL TO 
 | 
			
		||||
#   0x08c9                              similarequal ? ??? 
 | 
			
		||||
0x08cd "⇔" EEK_SYMBOL_CATEGORY_LETTER #                    ifonlyif ⇔ LEFT RIGHT DOUBLE ARROW 
 | 
			
		||||
0x08ce "⇒" EEK_SYMBOL_CATEGORY_LETTER #                     implies ⇒ RIGHTWARDS DOUBLE ARROW 
 | 
			
		||||
0x08cf "≡" EEK_SYMBOL_CATEGORY_LETTER #                   identical ≡ IDENTICAL TO 
 | 
			
		||||
0x08d6 "√" EEK_SYMBOL_CATEGORY_LETTER #                     radical √ SQUARE ROOT 
 | 
			
		||||
0x08da "⊂" EEK_SYMBOL_CATEGORY_LETTER #                  includedin ⊂ SUBSET OF 
 | 
			
		||||
0x08db "⊃" EEK_SYMBOL_CATEGORY_LETTER #                    includes ⊃ SUPERSET OF 
 | 
			
		||||
0x08dc "∩" EEK_SYMBOL_CATEGORY_LETTER #                intersection ∩ INTERSECTION 
 | 
			
		||||
0x08dd "∪" EEK_SYMBOL_CATEGORY_LETTER #                       union ∪ UNION 
 | 
			
		||||
0x08de "∧" EEK_SYMBOL_CATEGORY_LETTER #                  logicaland ∧ LOGICAL AND 
 | 
			
		||||
0x08df "∨" EEK_SYMBOL_CATEGORY_LETTER #                   logicalor ∨ LOGICAL OR 
 | 
			
		||||
0x08ef "∂" EEK_SYMBOL_CATEGORY_LETTER #           partialderivative ∂ PARTIAL DIFFERENTIAL 
 | 
			
		||||
0x08f6 "ƒ" EEK_SYMBOL_CATEGORY_LETTER #                    function ƒ LATIN SMALL LETTER F WITH HOOK 
 | 
			
		||||
0x08fb "←" EEK_SYMBOL_CATEGORY_LETTER #                   leftarrow ← LEFTWARDS ARROW 
 | 
			
		||||
0x08fc "↑" EEK_SYMBOL_CATEGORY_LETTER #                     uparrow ↑ UPWARDS ARROW 
 | 
			
		||||
0x08fd "→" EEK_SYMBOL_CATEGORY_LETTER #                  rightarrow → RIGHTWARDS ARROW 
 | 
			
		||||
0x08fe "↓" EEK_SYMBOL_CATEGORY_LETTER #                   downarrow ↓ DOWNWARDS ARROW 
 | 
			
		||||
0x09df "␢" EEK_SYMBOL_CATEGORY_LETTER #                       blank ␢ BLANK SYMBOL 
 | 
			
		||||
0x09e0 "◆" EEK_SYMBOL_CATEGORY_LETTER #                soliddiamond ◆ BLACK DIAMOND 
 | 
			
		||||
0x09e1 "▒" EEK_SYMBOL_CATEGORY_LETTER #                checkerboard ▒ MEDIUM SHADE 
 | 
			
		||||
0x09e2 "␉" EEK_SYMBOL_CATEGORY_LETTER #                          ht ␉ SYMBOL FOR HORIZONTAL TABULATION 
 | 
			
		||||
0x09e3 "␌" EEK_SYMBOL_CATEGORY_LETTER #                          ff ␌ SYMBOL FOR FORM FEED 
 | 
			
		||||
0x09e4 "␍" EEK_SYMBOL_CATEGORY_LETTER #                          cr ␍ SYMBOL FOR CARRIAGE RETURN 
 | 
			
		||||
0x09e5 "␊" EEK_SYMBOL_CATEGORY_LETTER #                          lf ␊ SYMBOL FOR LINE FEED 
 | 
			
		||||
0x09e8 "" EEK_SYMBOL_CATEGORY_LETTER #                          nl  SYMBOL FOR NEWLINE 
 | 
			
		||||
0x09e9 "␋" EEK_SYMBOL_CATEGORY_LETTER #                          vt ␋ SYMBOL FOR VERTICAL TABULATION 
 | 
			
		||||
0x09ea "┘" EEK_SYMBOL_CATEGORY_LETTER #              lowrightcorner ┘ BOX DRAWINGS LIGHT UP AND LEFT 
 | 
			
		||||
0x09eb "┐" EEK_SYMBOL_CATEGORY_LETTER #               uprightcorner ┐ BOX DRAWINGS LIGHT DOWN AND LEFT 
 | 
			
		||||
0x09ec "┌" EEK_SYMBOL_CATEGORY_LETTER #                upleftcorner ┌ BOX DRAWINGS LIGHT DOWN AND RIGHT 
 | 
			
		||||
0x09ed "└" EEK_SYMBOL_CATEGORY_LETTER #               lowleftcorner └ BOX DRAWINGS LIGHT UP AND RIGHT 
 | 
			
		||||
0x09ee "┼" EEK_SYMBOL_CATEGORY_LETTER #               crossinglines ┼ BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL 
 | 
			
		||||
#   0x09ef                            horizlinescan1 ? ??? 
 | 
			
		||||
#   0x09f0                            horizlinescan3 ? ??? 
 | 
			
		||||
0x09f1 "─" EEK_SYMBOL_CATEGORY_LETTER #              horizlinescan5 ─ BOX DRAWINGS LIGHT HORIZONTAL 
 | 
			
		||||
#   0x09f2                            horizlinescan7 ? ??? 
 | 
			
		||||
#   0x09f3                            horizlinescan9 ? ??? 
 | 
			
		||||
0x09f4 "├" EEK_SYMBOL_CATEGORY_LETTER #                       leftt ├ BOX DRAWINGS LIGHT VERTICAL AND RIGHT 
 | 
			
		||||
0x09f5 "┤" EEK_SYMBOL_CATEGORY_LETTER #                      rightt ┤ BOX DRAWINGS LIGHT VERTICAL AND LEFT 
 | 
			
		||||
0x09f6 "┴" EEK_SYMBOL_CATEGORY_LETTER #                        bott ┴ BOX DRAWINGS LIGHT UP AND HORIZONTAL 
 | 
			
		||||
0x09f7 "┬" EEK_SYMBOL_CATEGORY_LETTER #                        topt ┬ BOX DRAWINGS LIGHT DOWN AND HORIZONTAL 
 | 
			
		||||
0x09f8 "│" EEK_SYMBOL_CATEGORY_LETTER #                     vertbar │ BOX DRAWINGS LIGHT VERTICAL 
 | 
			
		||||
0x0aa1 " " EEK_SYMBOL_CATEGORY_LETTER #                     emspace   EM SPACE 
 | 
			
		||||
0x0aa2 " " EEK_SYMBOL_CATEGORY_LETTER #                     enspace   EN SPACE 
 | 
			
		||||
0x0aa3 " " EEK_SYMBOL_CATEGORY_LETTER #                    em3space   THREE-PER-EM SPACE 
 | 
			
		||||
0x0aa4 " " EEK_SYMBOL_CATEGORY_LETTER #                    em4space   FOUR-PER-EM SPACE 
 | 
			
		||||
0x0aa5 " " EEK_SYMBOL_CATEGORY_LETTER #                  digitspace   FIGURE SPACE 
 | 
			
		||||
0x0aa6 " " EEK_SYMBOL_CATEGORY_LETTER #                  punctspace   PUNCTUATION SPACE 
 | 
			
		||||
0x0aa7 " " EEK_SYMBOL_CATEGORY_LETTER #                   thinspace   THIN SPACE 
 | 
			
		||||
0x0aa8 " " EEK_SYMBOL_CATEGORY_LETTER #                   hairspace   HAIR SPACE 
 | 
			
		||||
0x0aa9 "—" EEK_SYMBOL_CATEGORY_LETTER #                      emdash — EM DASH 
 | 
			
		||||
0x0aaa "–" EEK_SYMBOL_CATEGORY_LETTER #                      endash – EN DASH 
 | 
			
		||||
#   0x0aac                               signifblank ? ??? 
 | 
			
		||||
0x0aae "…" EEK_SYMBOL_CATEGORY_LETTER #                    ellipsis … HORIZONTAL ELLIPSIS 
 | 
			
		||||
#   0x0aaf                           doubbaselinedot ? ??? 
 | 
			
		||||
0x0ab0 "⅓" EEK_SYMBOL_CATEGORY_LETTER #                    onethird ⅓ VULGAR FRACTION ONE THIRD 
 | 
			
		||||
0x0ab1 "⅔" EEK_SYMBOL_CATEGORY_LETTER #                   twothirds ⅔ VULGAR FRACTION TWO THIRDS 
 | 
			
		||||
0x0ab2 "⅕" EEK_SYMBOL_CATEGORY_LETTER #                    onefifth ⅕ VULGAR FRACTION ONE FIFTH 
 | 
			
		||||
0x0ab3 "⅖" EEK_SYMBOL_CATEGORY_LETTER #                   twofifths ⅖ VULGAR FRACTION TWO FIFTHS 
 | 
			
		||||
0x0ab4 "⅗" EEK_SYMBOL_CATEGORY_LETTER #                 threefifths ⅗ VULGAR FRACTION THREE FIFTHS 
 | 
			
		||||
0x0ab5 "⅘" EEK_SYMBOL_CATEGORY_LETTER #                  fourfifths ⅘ VULGAR FRACTION FOUR FIFTHS 
 | 
			
		||||
0x0ab6 "⅙" EEK_SYMBOL_CATEGORY_LETTER #                    onesixth ⅙ VULGAR FRACTION ONE SIXTH 
 | 
			
		||||
0x0ab7 "⅚" EEK_SYMBOL_CATEGORY_LETTER #                  fivesixths ⅚ VULGAR FRACTION FIVE SIXTHS 
 | 
			
		||||
0x0ab8 "℅" EEK_SYMBOL_CATEGORY_LETTER #                      careof ℅ CARE OF 
 | 
			
		||||
0x0abb "‒" EEK_SYMBOL_CATEGORY_LETTER #                     figdash ‒ FIGURE DASH 
 | 
			
		||||
0x0abc "〈" EEK_SYMBOL_CATEGORY_LETTER #            leftanglebracket 〈 LEFT-POINTING ANGLE BRACKET 
 | 
			
		||||
0x0abd "." EEK_SYMBOL_CATEGORY_LETTER #                decimalpoint . FULL STOP 
 | 
			
		||||
0x0abe "〉" EEK_SYMBOL_CATEGORY_LETTER #           rightanglebracket 〉 RIGHT-POINTING ANGLE BRACKET 
 | 
			
		||||
#   0x0abf                                    marker ? ??? 
 | 
			
		||||
0x0ac3 "⅛" EEK_SYMBOL_CATEGORY_LETTER #                   oneeighth ⅛ VULGAR FRACTION ONE EIGHTH 
 | 
			
		||||
0x0ac4 "⅜" EEK_SYMBOL_CATEGORY_LETTER #                threeeighths ⅜ VULGAR FRACTION THREE EIGHTHS 
 | 
			
		||||
0x0ac5 "⅝" EEK_SYMBOL_CATEGORY_LETTER #                 fiveeighths ⅝ VULGAR FRACTION FIVE EIGHTHS 
 | 
			
		||||
0x0ac6 "⅞" EEK_SYMBOL_CATEGORY_LETTER #                seveneighths ⅞ VULGAR FRACTION SEVEN EIGHTHS 
 | 
			
		||||
0x0ac9 "™" EEK_SYMBOL_CATEGORY_LETTER #                   trademark ™ TRADE MARK SIGN 
 | 
			
		||||
0x0aca "☓" EEK_SYMBOL_CATEGORY_LETTER #               signaturemark ☓ SALTIRE 
 | 
			
		||||
#   0x0acb                         trademarkincircle ? ??? 
 | 
			
		||||
0x0acc "◁" EEK_SYMBOL_CATEGORY_LETTER #            leftopentriangle ◁ WHITE LEFT-POINTING TRIANGLE 
 | 
			
		||||
0x0acd "▷" EEK_SYMBOL_CATEGORY_LETTER #           rightopentriangle ▷ WHITE RIGHT-POINTING TRIANGLE 
 | 
			
		||||
0x0ace "○" EEK_SYMBOL_CATEGORY_LETTER #                emopencircle ○ WHITE CIRCLE 
 | 
			
		||||
0x0acf "□" EEK_SYMBOL_CATEGORY_LETTER #             emopenrectangle □ WHITE SQUARE 
 | 
			
		||||
0x0ad0 "‘" EEK_SYMBOL_CATEGORY_LETTER #         leftsinglequotemark ‘ LEFT SINGLE QUOTATION MARK 
 | 
			
		||||
0x0ad1 "’" EEK_SYMBOL_CATEGORY_LETTER #        rightsinglequotemark ’ RIGHT SINGLE QUOTATION MARK 
 | 
			
		||||
0x0ad2 "“" EEK_SYMBOL_CATEGORY_LETTER #         leftdoublequotemark “ LEFT DOUBLE QUOTATION MARK 
 | 
			
		||||
0x0ad3 "”" EEK_SYMBOL_CATEGORY_LETTER #        rightdoublequotemark ” RIGHT DOUBLE QUOTATION MARK 
 | 
			
		||||
0x0ad4 "℞" EEK_SYMBOL_CATEGORY_LETTER #                prescription ℞ PRESCRIPTION TAKE 
 | 
			
		||||
0x0ad6 "′" EEK_SYMBOL_CATEGORY_LETTER #                     minutes ′ PRIME 
 | 
			
		||||
0x0ad7 "″" EEK_SYMBOL_CATEGORY_LETTER #                     seconds ″ DOUBLE PRIME 
 | 
			
		||||
0x0ad9 "✝" EEK_SYMBOL_CATEGORY_LETTER #                  latincross ✝ LATIN CROSS 
 | 
			
		||||
#   0x0ada                                  hexagram ? ??? 
 | 
			
		||||
0x0adb "▬" EEK_SYMBOL_CATEGORY_LETTER #            filledrectbullet ▬ BLACK RECTANGLE 
 | 
			
		||||
0x0adc "◀" EEK_SYMBOL_CATEGORY_LETTER #         filledlefttribullet ◀ BLACK LEFT-POINTING TRIANGLE 
 | 
			
		||||
0x0add "▶" EEK_SYMBOL_CATEGORY_LETTER #        filledrighttribullet ▶ BLACK RIGHT-POINTING TRIANGLE 
 | 
			
		||||
0x0ade "●" EEK_SYMBOL_CATEGORY_LETTER #              emfilledcircle ● BLACK CIRCLE 
 | 
			
		||||
0x0adf "■" EEK_SYMBOL_CATEGORY_LETTER #                emfilledrect ■ BLACK SQUARE 
 | 
			
		||||
0x0ae0 "◦" EEK_SYMBOL_CATEGORY_LETTER #            enopencircbullet ◦ WHITE BULLET 
 | 
			
		||||
0x0ae1 "▫" EEK_SYMBOL_CATEGORY_LETTER #          enopensquarebullet ▫ WHITE SMALL SQUARE 
 | 
			
		||||
0x0ae2 "▭" EEK_SYMBOL_CATEGORY_LETTER #              openrectbullet ▭ WHITE RECTANGLE 
 | 
			
		||||
0x0ae3 "△" EEK_SYMBOL_CATEGORY_LETTER #             opentribulletup △ WHITE UP-POINTING TRIANGLE 
 | 
			
		||||
0x0ae4 "▽" EEK_SYMBOL_CATEGORY_LETTER #           opentribulletdown ▽ WHITE DOWN-POINTING TRIANGLE 
 | 
			
		||||
0x0ae5 "☆" EEK_SYMBOL_CATEGORY_LETTER #                    openstar ☆ WHITE STAR 
 | 
			
		||||
0x0ae6 "•" EEK_SYMBOL_CATEGORY_LETTER #          enfilledcircbullet • BULLET 
 | 
			
		||||
0x0ae7 "▪" EEK_SYMBOL_CATEGORY_LETTER #            enfilledsqbullet ▪ BLACK SMALL SQUARE 
 | 
			
		||||
0x0ae8 "▲" EEK_SYMBOL_CATEGORY_LETTER #           filledtribulletup ▲ BLACK UP-POINTING TRIANGLE 
 | 
			
		||||
0x0ae9 "▼" EEK_SYMBOL_CATEGORY_LETTER #         filledtribulletdown ▼ BLACK DOWN-POINTING TRIANGLE 
 | 
			
		||||
0x0aea "☜" EEK_SYMBOL_CATEGORY_LETTER #                 leftpointer ☜ WHITE LEFT POINTING INDEX 
 | 
			
		||||
0x0aeb "☞" EEK_SYMBOL_CATEGORY_LETTER #                rightpointer ☞ WHITE RIGHT POINTING INDEX 
 | 
			
		||||
0x0aec "♣" EEK_SYMBOL_CATEGORY_LETTER #                        club ♣ BLACK CLUB SUIT 
 | 
			
		||||
0x0aed "♦" EEK_SYMBOL_CATEGORY_LETTER #                     diamond ♦ BLACK DIAMOND SUIT 
 | 
			
		||||
0x0aee "♥" EEK_SYMBOL_CATEGORY_LETTER #                       heart ♥ BLACK HEART SUIT 
 | 
			
		||||
0x0af0 "✠" EEK_SYMBOL_CATEGORY_LETTER #                maltesecross ✠ MALTESE CROSS 
 | 
			
		||||
0x0af1 "†" EEK_SYMBOL_CATEGORY_LETTER #                      dagger † DAGGER 
 | 
			
		||||
0x0af2 "‡" EEK_SYMBOL_CATEGORY_LETTER #                doubledagger ‡ DOUBLE DAGGER 
 | 
			
		||||
0x0af3 "✓" EEK_SYMBOL_CATEGORY_LETTER #                   checkmark ✓ CHECK MARK 
 | 
			
		||||
0x0af4 "✗" EEK_SYMBOL_CATEGORY_LETTER #                 ballotcross ✗ BALLOT X 
 | 
			
		||||
0x0af5 "♯" EEK_SYMBOL_CATEGORY_LETTER #                musicalsharp ♯ MUSIC SHARP SIGN 
 | 
			
		||||
0x0af6 "♭" EEK_SYMBOL_CATEGORY_LETTER #                 musicalflat ♭ MUSIC FLAT SIGN 
 | 
			
		||||
0x0af7 "♂" EEK_SYMBOL_CATEGORY_LETTER #                  malesymbol ♂ MALE SIGN 
 | 
			
		||||
0x0af8 "♀" EEK_SYMBOL_CATEGORY_LETTER #                femalesymbol ♀ FEMALE SIGN 
 | 
			
		||||
0x0af9 "☎" EEK_SYMBOL_CATEGORY_LETTER #                   telephone ☎ BLACK TELEPHONE 
 | 
			
		||||
0x0afa "⌕" EEK_SYMBOL_CATEGORY_LETTER #           telephonerecorder ⌕ TELEPHONE RECORDER 
 | 
			
		||||
0x0afb "℗" EEK_SYMBOL_CATEGORY_LETTER #         phonographcopyright ℗ SOUND RECORDING COPYRIGHT 
 | 
			
		||||
0x0afc "‸" EEK_SYMBOL_CATEGORY_LETTER #                       caret ‸ CARET 
 | 
			
		||||
0x0afd "‚" EEK_SYMBOL_CATEGORY_LETTER #          singlelowquotemark ‚ SINGLE LOW-9 QUOTATION MARK 
 | 
			
		||||
0x0afe "„" EEK_SYMBOL_CATEGORY_LETTER #          doublelowquotemark „ DOUBLE LOW-9 QUOTATION MARK 
 | 
			
		||||
#   0x0aff                                    cursor ? ??? 
 | 
			
		||||
0x0ba3 "<" EEK_SYMBOL_CATEGORY_LETTER #                   leftcaret < LESS-THAN SIGN 
 | 
			
		||||
0x0ba6 ">" EEK_SYMBOL_CATEGORY_LETTER #                  rightcaret > GREATER-THAN SIGN 
 | 
			
		||||
0x0ba8 "∨" EEK_SYMBOL_CATEGORY_LETTER #                   downcaret ∨ LOGICAL OR 
 | 
			
		||||
0x0ba9 "∧" EEK_SYMBOL_CATEGORY_LETTER #                     upcaret ∧ LOGICAL AND 
 | 
			
		||||
0x0bc0 "¯" EEK_SYMBOL_CATEGORY_LETTER #                     overbar ¯ MACRON 
 | 
			
		||||
0x0bc2 "⊤" EEK_SYMBOL_CATEGORY_LETTER #                    downtack ⊤ DOWN TACK 
 | 
			
		||||
0x0bc3 "∩" EEK_SYMBOL_CATEGORY_LETTER #                      upshoe ∩ INTERSECTION 
 | 
			
		||||
0x0bc4 "⌊" EEK_SYMBOL_CATEGORY_LETTER #                   downstile ⌊ LEFT FLOOR 
 | 
			
		||||
0x0bc6 "_" EEK_SYMBOL_CATEGORY_LETTER #                    underbar _ LOW LINE 
 | 
			
		||||
0x0bca "∘" EEK_SYMBOL_CATEGORY_LETTER #                         jot ∘ RING OPERATOR 
 | 
			
		||||
0x0bcc "⎕" EEK_SYMBOL_CATEGORY_LETTER #                        quad ⎕ APL FUNCTIONAL SYMBOL QUAD (Unicode 3.0) 
 | 
			
		||||
0x0bce "⊥" EEK_SYMBOL_CATEGORY_LETTER #                      uptack ⊥ UP TACK 
 | 
			
		||||
0x0bcf "○" EEK_SYMBOL_CATEGORY_LETTER #                      circle ○ WHITE CIRCLE 
 | 
			
		||||
0x0bd3 "⌈" EEK_SYMBOL_CATEGORY_LETTER #                     upstile ⌈ LEFT CEILING 
 | 
			
		||||
0x0bd6 "∪" EEK_SYMBOL_CATEGORY_LETTER #                    downshoe ∪ UNION 
 | 
			
		||||
0x0bd8 "⊃" EEK_SYMBOL_CATEGORY_LETTER #                   rightshoe ⊃ SUPERSET OF 
 | 
			
		||||
0x0bda "⊂" EEK_SYMBOL_CATEGORY_LETTER #                    leftshoe ⊂ SUBSET OF 
 | 
			
		||||
0x0bdc "⊣" EEK_SYMBOL_CATEGORY_LETTER #                    lefttack ⊣ LEFT TACK 
 | 
			
		||||
0x0bfc "⊢" EEK_SYMBOL_CATEGORY_LETTER #                   righttack ⊢ RIGHT TACK 
 | 
			
		||||
0x0cdf "‗" EEK_SYMBOL_CATEGORY_LETTER #        hebrew_doublelowline ‗ DOUBLE LOW LINE 
 | 
			
		||||
0x0ce0 "א" EEK_SYMBOL_CATEGORY_LETTER #                hebrew_aleph א HEBREW LETTER ALEF 
 | 
			
		||||
0x0ce1 "ב" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_bet ב HEBREW LETTER BET 
 | 
			
		||||
0x0ce2 "ג" EEK_SYMBOL_CATEGORY_LETTER #                hebrew_gimel ג HEBREW LETTER GIMEL 
 | 
			
		||||
0x0ce3 "ד" EEK_SYMBOL_CATEGORY_LETTER #                hebrew_dalet ד HEBREW LETTER DALET 
 | 
			
		||||
0x0ce4 "ה" EEK_SYMBOL_CATEGORY_LETTER #                   hebrew_he ה HEBREW LETTER HE 
 | 
			
		||||
0x0ce5 "ו" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_waw ו HEBREW LETTER VAV 
 | 
			
		||||
0x0ce6 "ז" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_zain ז HEBREW LETTER ZAYIN 
 | 
			
		||||
0x0ce7 "ח" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_chet ח HEBREW LETTER HET 
 | 
			
		||||
0x0ce8 "ט" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_tet ט HEBREW LETTER TET 
 | 
			
		||||
0x0ce9 "י" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_yod י HEBREW LETTER YOD 
 | 
			
		||||
0x0cea "ך" EEK_SYMBOL_CATEGORY_LETTER #            hebrew_finalkaph ך HEBREW LETTER FINAL KAF 
 | 
			
		||||
0x0ceb "כ" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_kaph כ HEBREW LETTER KAF 
 | 
			
		||||
0x0cec "ל" EEK_SYMBOL_CATEGORY_LETTER #                hebrew_lamed ל HEBREW LETTER LAMED 
 | 
			
		||||
0x0ced "ם" EEK_SYMBOL_CATEGORY_LETTER #             hebrew_finalmem ם HEBREW LETTER FINAL MEM 
 | 
			
		||||
0x0cee "מ" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_mem מ HEBREW LETTER MEM 
 | 
			
		||||
0x0cef "ן" EEK_SYMBOL_CATEGORY_LETTER #             hebrew_finalnun ן HEBREW LETTER FINAL NUN 
 | 
			
		||||
0x0cf0 "נ" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_nun נ HEBREW LETTER NUN 
 | 
			
		||||
0x0cf1 "ס" EEK_SYMBOL_CATEGORY_LETTER #               hebrew_samech ס HEBREW LETTER SAMEKH 
 | 
			
		||||
0x0cf2 "ע" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_ayin ע HEBREW LETTER AYIN 
 | 
			
		||||
0x0cf3 "ף" EEK_SYMBOL_CATEGORY_LETTER #              hebrew_finalpe ף HEBREW LETTER FINAL PE 
 | 
			
		||||
0x0cf4 "פ" EEK_SYMBOL_CATEGORY_LETTER #                   hebrew_pe פ HEBREW LETTER PE 
 | 
			
		||||
0x0cf5 "ץ" EEK_SYMBOL_CATEGORY_LETTER #            hebrew_finalzade ץ HEBREW LETTER FINAL TSADI 
 | 
			
		||||
0x0cf6 "צ" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_zade צ HEBREW LETTER TSADI 
 | 
			
		||||
0x0cf7 "ק" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_qoph ק HEBREW LETTER QOF 
 | 
			
		||||
0x0cf8 "ר" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_resh ר HEBREW LETTER RESH 
 | 
			
		||||
0x0cf9 "ש" EEK_SYMBOL_CATEGORY_LETTER #                 hebrew_shin ש HEBREW LETTER SHIN 
 | 
			
		||||
0x0cfa "ת" EEK_SYMBOL_CATEGORY_LETTER #                  hebrew_taw ת HEBREW LETTER TAV 
 | 
			
		||||
0x0da1 "ก" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_kokai ก THAI CHARACTER KO KAI 
 | 
			
		||||
0x0da2 "ข" EEK_SYMBOL_CATEGORY_LETTER #                Thai_khokhai ข THAI CHARACTER KHO KHAI 
 | 
			
		||||
0x0da3 "ฃ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_khokhuat ฃ THAI CHARACTER KHO KHUAT 
 | 
			
		||||
0x0da4 "ค" EEK_SYMBOL_CATEGORY_LETTER #               Thai_khokhwai ค THAI CHARACTER KHO KHWAI 
 | 
			
		||||
0x0da5 "ฅ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_khokhon ฅ THAI CHARACTER KHO KHON 
 | 
			
		||||
0x0da6 "ฆ" EEK_SYMBOL_CATEGORY_LETTER #             Thai_khorakhang ฆ THAI CHARACTER KHO RAKHANG 
 | 
			
		||||
0x0da7 "ง" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_ngongu ง THAI CHARACTER NGO NGU 
 | 
			
		||||
0x0da8 "จ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_chochan จ THAI CHARACTER CHO CHAN 
 | 
			
		||||
0x0da9 "ฉ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_choching ฉ THAI CHARACTER CHO CHING 
 | 
			
		||||
0x0daa "ช" EEK_SYMBOL_CATEGORY_LETTER #               Thai_chochang ช THAI CHARACTER CHO CHANG 
 | 
			
		||||
0x0dab "ซ" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_soso ซ THAI CHARACTER SO SO 
 | 
			
		||||
0x0dac "ฌ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_chochoe ฌ THAI CHARACTER CHO CHOE 
 | 
			
		||||
0x0dad "ญ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_yoying ญ THAI CHARACTER YO YING 
 | 
			
		||||
0x0dae "ฎ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_dochada ฎ THAI CHARACTER DO CHADA 
 | 
			
		||||
0x0daf "ฏ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_topatak ฏ THAI CHARACTER TO PATAK 
 | 
			
		||||
0x0db0 "ฐ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_thothan ฐ THAI CHARACTER THO THAN 
 | 
			
		||||
0x0db1 "ฑ" EEK_SYMBOL_CATEGORY_LETTER #          Thai_thonangmontho ฑ THAI CHARACTER THO NANGMONTHO 
 | 
			
		||||
0x0db2 "ฒ" EEK_SYMBOL_CATEGORY_LETTER #             Thai_thophuthao ฒ THAI CHARACTER THO PHUTHAO 
 | 
			
		||||
0x0db3 "ณ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_nonen ณ THAI CHARACTER NO NEN 
 | 
			
		||||
0x0db4 "ด" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_dodek ด THAI CHARACTER DO DEK 
 | 
			
		||||
0x0db5 "ต" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_totao ต THAI CHARACTER TO TAO 
 | 
			
		||||
0x0db6 "ถ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_thothung ถ THAI CHARACTER THO THUNG 
 | 
			
		||||
0x0db7 "ท" EEK_SYMBOL_CATEGORY_LETTER #              Thai_thothahan ท THAI CHARACTER THO THAHAN 
 | 
			
		||||
0x0db8 "ธ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_thothong ธ THAI CHARACTER THO THONG 
 | 
			
		||||
0x0db9 "น" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_nonu น THAI CHARACTER NO NU 
 | 
			
		||||
0x0dba "บ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_bobaimai บ THAI CHARACTER BO BAIMAI 
 | 
			
		||||
0x0dbb "ป" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_popla ป THAI CHARACTER PO PLA 
 | 
			
		||||
0x0dbc "ผ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_phophung ผ THAI CHARACTER PHO PHUNG 
 | 
			
		||||
0x0dbd "ฝ" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_fofa ฝ THAI CHARACTER FO FA 
 | 
			
		||||
0x0dbe "พ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_phophan พ THAI CHARACTER PHO PHAN 
 | 
			
		||||
0x0dbf "ฟ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_fofan ฟ THAI CHARACTER FO FAN 
 | 
			
		||||
0x0dc0 "ภ" EEK_SYMBOL_CATEGORY_LETTER #             Thai_phosamphao ภ THAI CHARACTER PHO SAMPHAO 
 | 
			
		||||
0x0dc1 "ม" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_moma ม THAI CHARACTER MO MA 
 | 
			
		||||
0x0dc2 "ย" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_yoyak ย THAI CHARACTER YO YAK 
 | 
			
		||||
0x0dc3 "ร" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_rorua ร THAI CHARACTER RO RUA 
 | 
			
		||||
0x0dc4 "ฤ" EEK_SYMBOL_CATEGORY_LETTER #                     Thai_ru ฤ THAI CHARACTER RU 
 | 
			
		||||
0x0dc5 "ล" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_loling ล THAI CHARACTER LO LING 
 | 
			
		||||
0x0dc6 "ฦ" EEK_SYMBOL_CATEGORY_LETTER #                     Thai_lu ฦ THAI CHARACTER LU 
 | 
			
		||||
0x0dc7 "ว" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_wowaen ว THAI CHARACTER WO WAEN 
 | 
			
		||||
0x0dc8 "ศ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_sosala ศ THAI CHARACTER SO SALA 
 | 
			
		||||
0x0dc9 "ษ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_sorusi ษ THAI CHARACTER SO RUSI 
 | 
			
		||||
0x0dca "ส" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_sosua ส THAI CHARACTER SO SUA 
 | 
			
		||||
0x0dcb "ห" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_hohip ห THAI CHARACTER HO HIP 
 | 
			
		||||
0x0dcc "ฬ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_lochula ฬ THAI CHARACTER LO CHULA 
 | 
			
		||||
0x0dcd "อ" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_oang อ THAI CHARACTER O ANG 
 | 
			
		||||
0x0dce "ฮ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_honokhuk ฮ THAI CHARACTER HO NOKHUK 
 | 
			
		||||
0x0dcf "ฯ" EEK_SYMBOL_CATEGORY_LETTER #              Thai_paiyannoi ฯ THAI CHARACTER PAIYANNOI 
 | 
			
		||||
0x0dd0 "ะ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_saraa ะ THAI CHARACTER SARA A 
 | 
			
		||||
0x0dd1 "ั" EEK_SYMBOL_CATEGORY_LETTER #             Thai_maihanakat ั THAI CHARACTER MAI HAN-AKAT 
 | 
			
		||||
0x0dd2 "า" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_saraaa า THAI CHARACTER SARA AA 
 | 
			
		||||
0x0dd3 "ำ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_saraam ำ THAI CHARACTER SARA AM 
 | 
			
		||||
0x0dd4 "ิ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_sarai ิ THAI CHARACTER SARA I 
 | 
			
		||||
0x0dd5 "ี" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_saraii ี THAI CHARACTER SARA II 
 | 
			
		||||
0x0dd6 "ึ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_saraue ึ THAI CHARACTER SARA UE 
 | 
			
		||||
0x0dd7 "ื" EEK_SYMBOL_CATEGORY_LETTER #                Thai_sarauee ื THAI CHARACTER SARA UEE 
 | 
			
		||||
0x0dd8 "ุ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_sarau ุ THAI CHARACTER SARA U 
 | 
			
		||||
0x0dd9 "ู" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_sarauu ู THAI CHARACTER SARA UU 
 | 
			
		||||
0x0dda "ฺ" EEK_SYMBOL_CATEGORY_LETTER #                Thai_phinthu ฺ THAI CHARACTER PHINTHU 
 | 
			
		||||
0x0dde "" EEK_SYMBOL_CATEGORY_LETTER #      Thai_maihanakat_maitho  ??? 
 | 
			
		||||
0x0ddf "฿" EEK_SYMBOL_CATEGORY_LETTER #                   Thai_baht ฿ THAI CURRENCY SYMBOL BAHT 
 | 
			
		||||
0x0de0 "เ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_sarae เ THAI CHARACTER SARA E 
 | 
			
		||||
0x0de1 "แ" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_saraae แ THAI CHARACTER SARA AE 
 | 
			
		||||
0x0de2 "โ" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_sarao โ THAI CHARACTER SARA O 
 | 
			
		||||
0x0de3 "ใ" EEK_SYMBOL_CATEGORY_LETTER #          Thai_saraaimaimuan ใ THAI CHARACTER SARA AI MAIMUAN 
 | 
			
		||||
0x0de4 "ไ" EEK_SYMBOL_CATEGORY_LETTER #         Thai_saraaimaimalai ไ THAI CHARACTER SARA AI MAIMALAI 
 | 
			
		||||
0x0de5 "ๅ" EEK_SYMBOL_CATEGORY_LETTER #            Thai_lakkhangyao ๅ THAI CHARACTER LAKKHANGYAO 
 | 
			
		||||
0x0de6 "ๆ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_maiyamok ๆ THAI CHARACTER MAIYAMOK 
 | 
			
		||||
0x0de7 "็" EEK_SYMBOL_CATEGORY_LETTER #              Thai_maitaikhu ็ THAI CHARACTER MAITAIKHU 
 | 
			
		||||
0x0de8 "่" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_maiek ่ THAI CHARACTER MAI EK 
 | 
			
		||||
0x0de9 "้" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_maitho ้ THAI CHARACTER MAI THO 
 | 
			
		||||
0x0dea "๊" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_maitri ๊ THAI CHARACTER MAI TRI 
 | 
			
		||||
0x0deb "๋" EEK_SYMBOL_CATEGORY_LETTER #            Thai_maichattawa ๋ THAI CHARACTER MAI CHATTAWA 
 | 
			
		||||
0x0dec "์" EEK_SYMBOL_CATEGORY_LETTER #            Thai_thanthakhat ์ THAI CHARACTER THANTHAKHAT 
 | 
			
		||||
0x0ded "ํ" EEK_SYMBOL_CATEGORY_LETTER #               Thai_nikhahit ํ THAI CHARACTER NIKHAHIT 
 | 
			
		||||
0x0df0 "๐" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_leksun ๐ THAI DIGIT ZERO 
 | 
			
		||||
0x0df1 "๑" EEK_SYMBOL_CATEGORY_LETTER #                Thai_leknung ๑ THAI DIGIT ONE 
 | 
			
		||||
0x0df2 "๒" EEK_SYMBOL_CATEGORY_LETTER #                Thai_leksong ๒ THAI DIGIT TWO 
 | 
			
		||||
0x0df3 "๓" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_leksam ๓ THAI DIGIT THREE 
 | 
			
		||||
0x0df4 "๔" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_leksi ๔ THAI DIGIT FOUR 
 | 
			
		||||
0x0df5 "๕" EEK_SYMBOL_CATEGORY_LETTER #                  Thai_lekha ๕ THAI DIGIT FIVE 
 | 
			
		||||
0x0df6 "๖" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_lekhok ๖ THAI DIGIT SIX 
 | 
			
		||||
0x0df7 "๗" EEK_SYMBOL_CATEGORY_LETTER #                Thai_lekchet ๗ THAI DIGIT SEVEN 
 | 
			
		||||
0x0df8 "๘" EEK_SYMBOL_CATEGORY_LETTER #                Thai_lekpaet ๘ THAI DIGIT EIGHT 
 | 
			
		||||
0x0df9 "๙" EEK_SYMBOL_CATEGORY_LETTER #                 Thai_lekkao ๙ THAI DIGIT NINE 
 | 
			
		||||
0x0ea1 "ㄱ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_Kiyeog ㄱ HANGUL LETTER KIYEOK 
 | 
			
		||||
0x0ea2 "ㄲ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_SsangKiyeog ㄲ HANGUL LETTER SSANGKIYEOK 
 | 
			
		||||
0x0ea3 "ㄳ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_KiyeogSios ㄳ HANGUL LETTER KIYEOK-SIOS 
 | 
			
		||||
0x0ea4 "ㄴ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Nieun ㄴ HANGUL LETTER NIEUN 
 | 
			
		||||
0x0ea5 "ㄵ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_NieunJieuj ㄵ HANGUL LETTER NIEUN-CIEUC 
 | 
			
		||||
0x0ea6 "ㄶ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_NieunHieuh ㄶ HANGUL LETTER NIEUN-HIEUH 
 | 
			
		||||
0x0ea7 "ㄷ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_Dikeud ㄷ HANGUL LETTER TIKEUT 
 | 
			
		||||
0x0ea8 "ㄸ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_SsangDikeud ㄸ HANGUL LETTER SSANGTIKEUT 
 | 
			
		||||
0x0ea9 "ㄹ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Rieul ㄹ HANGUL LETTER RIEUL 
 | 
			
		||||
0x0eaa "ㄺ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_RieulKiyeog ㄺ HANGUL LETTER RIEUL-KIYEOK 
 | 
			
		||||
0x0eab "ㄻ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_RieulMieum ㄻ HANGUL LETTER RIEUL-MIEUM 
 | 
			
		||||
0x0eac "ㄼ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_RieulPieub ㄼ HANGUL LETTER RIEUL-PIEUP 
 | 
			
		||||
0x0ead "ㄽ" EEK_SYMBOL_CATEGORY_LETTER #            Hangul_RieulSios ㄽ HANGUL LETTER RIEUL-SIOS 
 | 
			
		||||
0x0eae "ㄾ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_RieulTieut ㄾ HANGUL LETTER RIEUL-THIEUTH 
 | 
			
		||||
0x0eaf "ㄿ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_RieulPhieuf ㄿ HANGUL LETTER RIEUL-PHIEUPH 
 | 
			
		||||
0x0eb0 "ㅀ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_RieulHieuh ㅀ HANGUL LETTER RIEUL-HIEUH 
 | 
			
		||||
0x0eb1 "ㅁ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Mieum ㅁ HANGUL LETTER MIEUM 
 | 
			
		||||
0x0eb2 "ㅂ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Pieub ㅂ HANGUL LETTER PIEUP 
 | 
			
		||||
0x0eb3 "ㅃ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_SsangPieub ㅃ HANGUL LETTER SSANGPIEUP 
 | 
			
		||||
0x0eb4 "ㅄ" EEK_SYMBOL_CATEGORY_LETTER #            Hangul_PieubSios ㅄ HANGUL LETTER PIEUP-SIOS 
 | 
			
		||||
0x0eb5 "ㅅ" EEK_SYMBOL_CATEGORY_LETTER #                 Hangul_Sios ㅅ HANGUL LETTER SIOS 
 | 
			
		||||
0x0eb6 "ㅆ" EEK_SYMBOL_CATEGORY_LETTER #            Hangul_SsangSios ㅆ HANGUL LETTER SSANGSIOS 
 | 
			
		||||
0x0eb7 "ㅇ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Ieung ㅇ HANGUL LETTER IEUNG 
 | 
			
		||||
0x0eb8 "ㅈ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Jieuj ㅈ HANGUL LETTER CIEUC 
 | 
			
		||||
0x0eb9 "ㅉ" EEK_SYMBOL_CATEGORY_LETTER #           Hangul_SsangJieuj ㅉ HANGUL LETTER SSANGCIEUC 
 | 
			
		||||
0x0eba "ㅊ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Cieuc ㅊ HANGUL LETTER CHIEUCH 
 | 
			
		||||
0x0ebb "ㅋ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_Khieuq ㅋ HANGUL LETTER KHIEUKH 
 | 
			
		||||
0x0ebc "ㅌ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Tieut ㅌ HANGUL LETTER THIEUTH 
 | 
			
		||||
0x0ebd "ㅍ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_Phieuf ㅍ HANGUL LETTER PHIEUPH 
 | 
			
		||||
0x0ebe "ㅎ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_Hieuh ㅎ HANGUL LETTER HIEUH 
 | 
			
		||||
0x0ebf "ㅏ" EEK_SYMBOL_CATEGORY_LETTER #                    Hangul_A ㅏ HANGUL LETTER A 
 | 
			
		||||
0x0ec0 "ㅐ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_AE ㅐ HANGUL LETTER AE 
 | 
			
		||||
0x0ec1 "ㅑ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_YA ㅑ HANGUL LETTER YA 
 | 
			
		||||
0x0ec2 "ㅒ" EEK_SYMBOL_CATEGORY_LETTER #                  Hangul_YAE ㅒ HANGUL LETTER YAE 
 | 
			
		||||
0x0ec3 "ㅓ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_EO ㅓ HANGUL LETTER EO 
 | 
			
		||||
0x0ec4 "ㅔ" EEK_SYMBOL_CATEGORY_LETTER #                    Hangul_E ㅔ HANGUL LETTER E 
 | 
			
		||||
0x0ec5 "ㅕ" EEK_SYMBOL_CATEGORY_LETTER #                  Hangul_YEO ㅕ HANGUL LETTER YEO 
 | 
			
		||||
0x0ec6 "ㅖ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_YE ㅖ HANGUL LETTER YE 
 | 
			
		||||
0x0ec7 "ㅗ" EEK_SYMBOL_CATEGORY_LETTER #                    Hangul_O ㅗ HANGUL LETTER O 
 | 
			
		||||
0x0ec8 "ㅘ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_WA ㅘ HANGUL LETTER WA 
 | 
			
		||||
0x0ec9 "ㅙ" EEK_SYMBOL_CATEGORY_LETTER #                  Hangul_WAE ㅙ HANGUL LETTER WAE 
 | 
			
		||||
0x0eca "ㅚ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_OE ㅚ HANGUL LETTER OE 
 | 
			
		||||
0x0ecb "ㅛ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_YO ㅛ HANGUL LETTER YO 
 | 
			
		||||
0x0ecc "ㅜ" EEK_SYMBOL_CATEGORY_LETTER #                    Hangul_U ㅜ HANGUL LETTER U 
 | 
			
		||||
0x0ecd "ㅝ" EEK_SYMBOL_CATEGORY_LETTER #                  Hangul_WEO ㅝ HANGUL LETTER WEO 
 | 
			
		||||
0x0ece "ㅞ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_WE ㅞ HANGUL LETTER WE 
 | 
			
		||||
0x0ecf "ㅟ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_WI ㅟ HANGUL LETTER WI 
 | 
			
		||||
0x0ed0 "ㅠ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_YU ㅠ HANGUL LETTER YU 
 | 
			
		||||
0x0ed1 "ㅡ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_EU ㅡ HANGUL LETTER EU 
 | 
			
		||||
0x0ed2 "ㅢ" EEK_SYMBOL_CATEGORY_LETTER #                   Hangul_YI ㅢ HANGUL LETTER YI 
 | 
			
		||||
0x0ed3 "ㅣ" EEK_SYMBOL_CATEGORY_LETTER #                    Hangul_I ㅣ HANGUL LETTER I 
 | 
			
		||||
0x0ed4 "ᆨ" EEK_SYMBOL_CATEGORY_LETTER #             Hangul_J_Kiyeog ᆨ HANGUL JONGSEONG KIYEOK 
 | 
			
		||||
0x0ed5 "ᆩ" EEK_SYMBOL_CATEGORY_LETTER #        Hangul_J_SsangKiyeog ᆩ HANGUL JONGSEONG SSANGKIYEOK 
 | 
			
		||||
0x0ed6 "ᆪ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_KiyeogSios ᆪ HANGUL JONGSEONG KIYEOK-SIOS 
 | 
			
		||||
0x0ed7 "ᆫ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Nieun ᆫ HANGUL JONGSEONG NIEUN 
 | 
			
		||||
0x0ed8 "ᆬ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_NieunJieuj ᆬ HANGUL JONGSEONG NIEUN-CIEUC 
 | 
			
		||||
0x0ed9 "ᆭ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_NieunHieuh ᆭ HANGUL JONGSEONG NIEUN-HIEUH 
 | 
			
		||||
0x0eda "ᆮ" EEK_SYMBOL_CATEGORY_LETTER #             Hangul_J_Dikeud ᆮ HANGUL JONGSEONG TIKEUT 
 | 
			
		||||
0x0edb "ᆯ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Rieul ᆯ HANGUL JONGSEONG RIEUL 
 | 
			
		||||
0x0edc "ᆰ" EEK_SYMBOL_CATEGORY_LETTER #        Hangul_J_RieulKiyeog ᆰ HANGUL JONGSEONG RIEUL-KIYEOK 
 | 
			
		||||
0x0edd "ᆱ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_RieulMieum ᆱ HANGUL JONGSEONG RIEUL-MIEUM 
 | 
			
		||||
0x0ede "ᆲ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_RieulPieub ᆲ HANGUL JONGSEONG RIEUL-PIEUP 
 | 
			
		||||
0x0edf "ᆳ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_J_RieulSios ᆳ HANGUL JONGSEONG RIEUL-SIOS 
 | 
			
		||||
0x0ee0 "ᆴ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_RieulTieut ᆴ HANGUL JONGSEONG RIEUL-THIEUTH 
 | 
			
		||||
0x0ee1 "ᆵ" EEK_SYMBOL_CATEGORY_LETTER #        Hangul_J_RieulPhieuf ᆵ HANGUL JONGSEONG RIEUL-PHIEUPH 
 | 
			
		||||
0x0ee2 "ᆶ" EEK_SYMBOL_CATEGORY_LETTER #         Hangul_J_RieulHieuh ᆶ HANGUL JONGSEONG RIEUL-HIEUH 
 | 
			
		||||
0x0ee3 "ᆷ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Mieum ᆷ HANGUL JONGSEONG MIEUM 
 | 
			
		||||
0x0ee4 "ᆸ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Pieub ᆸ HANGUL JONGSEONG PIEUP 
 | 
			
		||||
0x0ee5 "ᆹ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_J_PieubSios ᆹ HANGUL JONGSEONG PIEUP-SIOS 
 | 
			
		||||
0x0ee6 "ᆺ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_J_Sios ᆺ HANGUL JONGSEONG SIOS 
 | 
			
		||||
0x0ee7 "ᆻ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_J_SsangSios ᆻ HANGUL JONGSEONG SSANGSIOS 
 | 
			
		||||
0x0ee8 "ᆼ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Ieung ᆼ HANGUL JONGSEONG IEUNG 
 | 
			
		||||
0x0ee9 "ᆽ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Jieuj ᆽ HANGUL JONGSEONG CIEUC 
 | 
			
		||||
0x0eea "ᆾ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Cieuc ᆾ HANGUL JONGSEONG CHIEUCH 
 | 
			
		||||
0x0eeb "ᆿ" EEK_SYMBOL_CATEGORY_LETTER #             Hangul_J_Khieuq ᆿ HANGUL JONGSEONG KHIEUKH 
 | 
			
		||||
0x0eec "ᇀ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Tieut ᇀ HANGUL JONGSEONG THIEUTH 
 | 
			
		||||
0x0eed "ᇁ" EEK_SYMBOL_CATEGORY_LETTER #             Hangul_J_Phieuf ᇁ HANGUL JONGSEONG PHIEUPH 
 | 
			
		||||
0x0eee "ᇂ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_J_Hieuh ᇂ HANGUL JONGSEONG HIEUH 
 | 
			
		||||
0x0eef "ㅭ" EEK_SYMBOL_CATEGORY_LETTER #     Hangul_RieulYeorinHieuh ㅭ HANGUL LETTER RIEUL-YEORINHIEUH 
 | 
			
		||||
0x0ef0 "ㅱ" EEK_SYMBOL_CATEGORY_LETTER #    Hangul_SunkyeongeumMieum ㅱ HANGUL LETTER KAPYEOUNMIEUM 
 | 
			
		||||
0x0ef1 "ㅸ" EEK_SYMBOL_CATEGORY_LETTER #    Hangul_SunkyeongeumPieub ㅸ HANGUL LETTER KAPYEOUNPIEUP 
 | 
			
		||||
0x0ef2 "ㅿ" EEK_SYMBOL_CATEGORY_LETTER #              Hangul_PanSios ㅿ HANGUL LETTER PANSIOS 
 | 
			
		||||
#   0x0ef3                  Hangul_KkogjiDalrinIeung ? ??? 
 | 
			
		||||
0x0ef4 "ㆄ" EEK_SYMBOL_CATEGORY_LETTER #   Hangul_SunkyeongeumPhieuf ㆄ HANGUL LETTER KAPYEOUNPHIEUPH 
 | 
			
		||||
0x0ef5 "ㆆ" EEK_SYMBOL_CATEGORY_LETTER #          Hangul_YeorinHieuh ㆆ HANGUL LETTER YEORINHIEUH 
 | 
			
		||||
0x0ef6 "ㆍ" EEK_SYMBOL_CATEGORY_LETTER #                Hangul_AraeA ㆍ HANGUL LETTER ARAEA 
 | 
			
		||||
0x0ef7 "ㆎ" EEK_SYMBOL_CATEGORY_LETTER #               Hangul_AraeAE ㆎ HANGUL LETTER ARAEAE 
 | 
			
		||||
0x0ef8 "ᇫ" EEK_SYMBOL_CATEGORY_LETTER #            Hangul_J_PanSios ᇫ HANGUL JONGSEONG PANSIOS 
 | 
			
		||||
#   0x0ef9                Hangul_J_KkogjiDalrinIeung ? ??? 
 | 
			
		||||
0x0efa "ᇹ" EEK_SYMBOL_CATEGORY_LETTER #        Hangul_J_YeorinHieuh ᇹ HANGUL JONGSEONG YEORINHIEUH 
 | 
			
		||||
0x0eff "₩" EEK_SYMBOL_CATEGORY_LETTER #                  Korean_Won ₩ WON SIGN 
 | 
			
		||||
0x13bc "Œ" EEK_SYMBOL_CATEGORY_LETTER #                          OE Œ LATIN CAPITAL LIGATURE OE 
 | 
			
		||||
0x13bd "œ" EEK_SYMBOL_CATEGORY_LETTER #                          oe œ LATIN SMALL LIGATURE OE 
 | 
			
		||||
0x13be "Ÿ" EEK_SYMBOL_CATEGORY_LETTER #                  Ydiaeresis Ÿ LATIN CAPITAL LETTER Y WITH DIAERESIS 
 | 
			
		||||
0x20a0 "₠" EEK_SYMBOL_CATEGORY_LETTER #                     EcuSign ₠ EURO-CURRENCY SIGN 
 | 
			
		||||
0x20a1 "₡" EEK_SYMBOL_CATEGORY_LETTER #                   ColonSign ₡ COLON SIGN 
 | 
			
		||||
0x20a2 "₢" EEK_SYMBOL_CATEGORY_LETTER #                CruzeiroSign ₢ CRUZEIRO SIGN 
 | 
			
		||||
0x20a3 "₣" EEK_SYMBOL_CATEGORY_LETTER #                  FFrancSign ₣ FRENCH FRANC SIGN 
 | 
			
		||||
0x20a4 "₤" EEK_SYMBOL_CATEGORY_LETTER #                    LiraSign ₤ LIRA SIGN 
 | 
			
		||||
0x20a5 "₥" EEK_SYMBOL_CATEGORY_LETTER #                    MillSign ₥ MILL SIGN 
 | 
			
		||||
0x20a6 "₦" EEK_SYMBOL_CATEGORY_LETTER #                   NairaSign ₦ NAIRA SIGN 
 | 
			
		||||
0x20a7 "₧" EEK_SYMBOL_CATEGORY_LETTER #                  PesetaSign ₧ PESETA SIGN 
 | 
			
		||||
0x20a8 "₨" EEK_SYMBOL_CATEGORY_LETTER #                   RupeeSign ₨ RUPEE SIGN 
 | 
			
		||||
0x20a9 "₩" EEK_SYMBOL_CATEGORY_LETTER #                     WonSign ₩ WON SIGN 
 | 
			
		||||
0x20aa "₪" EEK_SYMBOL_CATEGORY_LETTER #               NewSheqelSign ₪ NEW SHEQEL SIGN 
 | 
			
		||||
0x20ab "₫" EEK_SYMBOL_CATEGORY_LETTER #                    DongSign ₫ DONG SIGN 
 | 
			
		||||
0x20ac "€" EEK_SYMBOL_CATEGORY_LETTER #                    EuroSign € EURO SIGN 
 | 
			
		||||
 | 
			
		||||
#  Following items added to GTK, not in the xterm table 
 | 
			
		||||
 | 
			
		||||
#  Numeric keypad 
 | 
			
		||||
  
 | 
			
		||||
# 0xFF80   # Space *
 | 
			
		||||
0xFFAA "*" EEK_SYMBOL_CATEGORY_LETTER # Multiply *
 | 
			
		||||
0xFFAB "+" EEK_SYMBOL_CATEGORY_LETTER # Add *
 | 
			
		||||
0xFFAC "," EEK_SYMBOL_CATEGORY_LETTER # Separator *
 | 
			
		||||
0xFFAD "-" EEK_SYMBOL_CATEGORY_LETTER # Subtract *
 | 
			
		||||
0xFFAE "." EEK_SYMBOL_CATEGORY_LETTER # Decimal *
 | 
			
		||||
0xFFAF "/" EEK_SYMBOL_CATEGORY_LETTER # Divide *
 | 
			
		||||
0xFFB0 "0" EEK_SYMBOL_CATEGORY_LETTER # 0 *
 | 
			
		||||
0xFFB1 "1" EEK_SYMBOL_CATEGORY_LETTER # 1 *
 | 
			
		||||
0xFFB2 "2" EEK_SYMBOL_CATEGORY_LETTER # 2 *
 | 
			
		||||
0xFFB3 "3" EEK_SYMBOL_CATEGORY_LETTER # 3 *
 | 
			
		||||
0xFFB4 "4" EEK_SYMBOL_CATEGORY_LETTER # 4 *
 | 
			
		||||
0xFFB5 "5" EEK_SYMBOL_CATEGORY_LETTER # 5 *
 | 
			
		||||
0xFFB6 "6" EEK_SYMBOL_CATEGORY_LETTER # 6 *
 | 
			
		||||
0xFFB7 "7" EEK_SYMBOL_CATEGORY_LETTER # 7 *
 | 
			
		||||
0xFFB8 "8" EEK_SYMBOL_CATEGORY_LETTER # 8 *
 | 
			
		||||
0xFFB9 "9" EEK_SYMBOL_CATEGORY_LETTER # 9 *
 | 
			
		||||
0xFFBD "=" EEK_SYMBOL_CATEGORY_LETTER # Equal *  
 | 
			
		||||
 | 
			
		||||
#  End numeric keypad 
 | 
			
		||||
@ -71,10 +71,11 @@ struct _EekboardContextServicePrivate {
 | 
			
		||||
    gboolean visible;
 | 
			
		||||
    gboolean fullscreen;
 | 
			
		||||
 | 
			
		||||
    LevelKeyboard *keyboard; // currently used keyboard
 | 
			
		||||
    EekKeyboard *keyboard; // currently used keyboard
 | 
			
		||||
    GHashTable *keyboard_hash; // a table of available keyboards, per layout
 | 
			
		||||
 | 
			
		||||
    // TODO: make use of repeating buttons
 | 
			
		||||
    EekKey *repeat_key;
 | 
			
		||||
    guint repeat_timeout_id;
 | 
			
		||||
    gboolean repeat_triggered;
 | 
			
		||||
 | 
			
		||||
@ -85,10 +86,11 @@ struct _EekboardContextServicePrivate {
 | 
			
		||||
 | 
			
		||||
G_DEFINE_TYPE_WITH_PRIVATE (EekboardContextService, eekboard_context_service, G_TYPE_OBJECT);
 | 
			
		||||
 | 
			
		||||
static LevelKeyboard *
 | 
			
		||||
static EekKeyboard *
 | 
			
		||||
eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
			
		||||
                                               const gchar            *keyboard_type)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekLayout *layout;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
@ -133,7 +135,7 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    LevelKeyboard *keyboard = eek_xml_layout_real_create_keyboard(layout, self);
 | 
			
		||||
    keyboard = eek_keyboard_new (self, layout, CSW, CSH);
 | 
			
		||||
    if (!keyboard) {
 | 
			
		||||
        g_error("Failed to create a keyboard");
 | 
			
		||||
    }
 | 
			
		||||
@ -146,19 +148,15 @@ eekboard_context_service_real_create_keyboard (EekboardContextService *self,
 | 
			
		||||
 | 
			
		||||
    gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
 | 
			
		||||
 | 
			
		||||
    int f = open("maprs.map", O_CREAT | O_WRONLY, 0600);
 | 
			
		||||
    write(f, keymap_str, strlen(keymap_str));
 | 
			
		||||
    close(f);
 | 
			
		||||
 | 
			
		||||
    struct xkb_keymap *keymap = xkb_keymap_new_from_string(context, keymap_str,
 | 
			
		||||
        XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
 | 
			
		||||
 | 
			
		||||
    if (!keymap)
 | 
			
		||||
        g_error("Bad keymap:\n%s", keymap_str);
 | 
			
		||||
 | 
			
		||||
    free(keymap_str);
 | 
			
		||||
 | 
			
		||||
    xkb_context_unref(context);
 | 
			
		||||
    if (!keymap) {
 | 
			
		||||
        g_error("Bad keymap");
 | 
			
		||||
    }
 | 
			
		||||
    keyboard->keymap = keymap;
 | 
			
		||||
 | 
			
		||||
    keymap_str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
 | 
			
		||||
@ -317,16 +315,21 @@ settings_update_layout(EekboardContextService *context)
 | 
			
		||||
 | 
			
		||||
    // generic part follows
 | 
			
		||||
    static guint keyboard_id = 0;
 | 
			
		||||
    LevelKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
 | 
			
		||||
    EekKeyboard *keyboard = g_hash_table_lookup(context->priv->keyboard_hash,
 | 
			
		||||
                                                GUINT_TO_POINTER(keyboard_id));
 | 
			
		||||
    // create a keyboard
 | 
			
		||||
    if (!keyboard) {
 | 
			
		||||
        keyboard = eekboard_context_service_real_create_keyboard(context, keyboard_layout);
 | 
			
		||||
        EekboardContextServiceClass *klass = EEKBOARD_CONTEXT_SERVICE_GET_CLASS(context);
 | 
			
		||||
        keyboard = klass->create_keyboard (context, keyboard_layout);
 | 
			
		||||
        eek_keyboard_set_modifier_behavior (keyboard,
 | 
			
		||||
                                            EEK_MODIFIER_BEHAVIOR_LATCH);
 | 
			
		||||
 | 
			
		||||
        g_hash_table_insert (context->priv->keyboard_hash,
 | 
			
		||||
                             GUINT_TO_POINTER(keyboard_id),
 | 
			
		||||
                             keyboard);
 | 
			
		||||
        keyboard->id = keyboard_id;
 | 
			
		||||
        g_object_set_data (G_OBJECT(keyboard),
 | 
			
		||||
                           "keyboard-id",
 | 
			
		||||
                           GUINT_TO_POINTER(keyboard_id));
 | 
			
		||||
        keyboard_id++;
 | 
			
		||||
    }
 | 
			
		||||
    // set as current
 | 
			
		||||
@ -367,6 +370,7 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
 | 
			
		||||
    GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 | 
			
		||||
    GParamSpec *pspec;
 | 
			
		||||
 | 
			
		||||
    klass->create_keyboard = eekboard_context_service_real_create_keyboard;
 | 
			
		||||
    klass->show_keyboard = eekboard_context_service_real_show_keyboard;
 | 
			
		||||
    klass->hide_keyboard = eekboard_context_service_real_hide_keyboard;
 | 
			
		||||
 | 
			
		||||
@ -431,9 +435,10 @@ eekboard_context_service_class_init (EekboardContextServiceClass *klass)
 | 
			
		||||
     *
 | 
			
		||||
     * An #EekKeyboard currently active in this context.
 | 
			
		||||
     */
 | 
			
		||||
    pspec = g_param_spec_pointer("keyboard",
 | 
			
		||||
    pspec = g_param_spec_object ("keyboard",
 | 
			
		||||
                                 "Keyboard",
 | 
			
		||||
                                 "Keyboard",
 | 
			
		||||
                                 EEK_TYPE_KEYBOARD,
 | 
			
		||||
                                 G_PARAM_READWRITE);
 | 
			
		||||
    g_object_class_install_property (gobject_class,
 | 
			
		||||
                                     PROP_KEYBOARD,
 | 
			
		||||
@ -569,7 +574,7 @@ eekboard_context_service_destroy (EekboardContextService *context)
 | 
			
		||||
 * Get keyboard currently active in @context.
 | 
			
		||||
 * Returns: (transfer none): an #EekKeyboard
 | 
			
		||||
 */
 | 
			
		||||
LevelKeyboard *
 | 
			
		||||
EekKeyboard *
 | 
			
		||||
eekboard_context_service_get_keyboard (EekboardContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    return context->priv->keyboard;
 | 
			
		||||
@ -589,7 +594,7 @@ eekboard_context_service_get_fullscreen (EekboardContextService *context)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
			
		||||
                                         const LevelKeyboard *keyboard)
 | 
			
		||||
                                         const EekKeyboard *keyboard)
 | 
			
		||||
{
 | 
			
		||||
    zwp_virtual_keyboard_v1_keymap(context->virtual_keyboard,
 | 
			
		||||
        WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
 | 
			
		||||
 | 
			
		||||
@ -73,7 +73,7 @@ struct _EekboardContextServiceClass {
 | 
			
		||||
    GObjectClass parent_class;
 | 
			
		||||
 | 
			
		||||
    /*< public >*/
 | 
			
		||||
    struct squeek_view *(*create_keyboard)    (EekboardContextService *self,
 | 
			
		||||
    EekKeyboard *(*create_keyboard)    (EekboardContextService *self,
 | 
			
		||||
                                        const gchar            *keyboard_type);
 | 
			
		||||
    void         (*show_keyboard)      (EekboardContextService *self);
 | 
			
		||||
    void         (*hide_keyboard)      (EekboardContextService *self);
 | 
			
		||||
@ -97,12 +97,13 @@ void          eekboard_context_service_show_keyboard
 | 
			
		||||
void          eekboard_context_service_hide_keyboard
 | 
			
		||||
                                              (EekboardContextService *context);
 | 
			
		||||
void          eekboard_context_service_destroy (EekboardContextService *context);
 | 
			
		||||
LevelKeyboard *eekboard_context_service_get_keyboard(EekboardContextService *context);
 | 
			
		||||
EekKeyboard  *eekboard_context_service_get_keyboard
 | 
			
		||||
                                              (EekboardContextService *context);
 | 
			
		||||
gboolean      eekboard_context_service_get_fullscreen
 | 
			
		||||
                                              (EekboardContextService *context);
 | 
			
		||||
 | 
			
		||||
void eekboard_context_service_set_keymap(EekboardContextService *context,
 | 
			
		||||
                                         const LevelKeyboard *keyboard);
 | 
			
		||||
                                         const EekKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
void eekboard_context_service_set_hint_purpose(EekboardContextService *context,
 | 
			
		||||
                                               uint32_t hint,
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ enum {
 | 
			
		||||
    ENABLED,
 | 
			
		||||
    DISABLED,
 | 
			
		||||
    DESTROYED,
 | 
			
		||||
    KEY_ACTIVATED,
 | 
			
		||||
    LAST_SIGNAL
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -80,6 +81,28 @@ eekboard_context_real_g_signal (GDBusProxy  *self,
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (signal_name, "KeyActivated") == 0) {
 | 
			
		||||
        guint keycode;
 | 
			
		||||
        GVariant *variant = NULL;
 | 
			
		||||
        guint modifiers = 0;
 | 
			
		||||
        EekSerializable *serializable;
 | 
			
		||||
 | 
			
		||||
        g_variant_get (parameters, "(uvu)",
 | 
			
		||||
                       &keycode, &variant, &modifiers);
 | 
			
		||||
        g_return_if_fail (variant != NULL);
 | 
			
		||||
 | 
			
		||||
        serializable = eek_serializable_deserialize (variant);
 | 
			
		||||
        g_variant_unref (variant);
 | 
			
		||||
 | 
			
		||||
        g_return_if_fail (EEK_IS_SYMBOL(serializable));
 | 
			
		||||
        
 | 
			
		||||
        g_signal_emit (context, signals[KEY_ACTIVATED], 0,
 | 
			
		||||
                       keycode, EEK_SYMBOL(serializable), modifiers);
 | 
			
		||||
        g_object_unref (serializable);
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (g_strcmp0 (signal_name, "VisibilityChanged") == 0) {
 | 
			
		||||
        gboolean visible = FALSE;
 | 
			
		||||
 | 
			
		||||
@ -126,6 +149,14 @@ eekboard_context_real_destroyed (EekboardContext *self)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_context_real_key_activated (EekboardContext *self,
 | 
			
		||||
                                     guint            keycode,
 | 
			
		||||
                                     EekSymbol       *symbol,
 | 
			
		||||
                                     guint            modifiers)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
eekboard_context_get_property (GObject    *object,
 | 
			
		||||
                               guint       prop_id,
 | 
			
		||||
@ -155,6 +186,7 @@ eekboard_context_class_init (EekboardContextClass *klass)
 | 
			
		||||
    klass->enabled = eekboard_context_real_enabled;
 | 
			
		||||
    klass->disabled = eekboard_context_real_disabled;
 | 
			
		||||
    klass->destroyed = eekboard_context_real_destroyed;
 | 
			
		||||
    klass->key_activated = eekboard_context_real_key_activated;
 | 
			
		||||
 | 
			
		||||
    proxy_class->g_signal = eekboard_context_real_g_signal;
 | 
			
		||||
 | 
			
		||||
@ -208,6 +240,31 @@ eekboard_context_class_init (EekboardContextClass *klass)
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      0);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * EekboardContext::key-activated:
 | 
			
		||||
     * @context: an #EekboardContext
 | 
			
		||||
     * @keycode: a keycode
 | 
			
		||||
     * @symbol: an #EekSymbol
 | 
			
		||||
     * @modifiers: modifiers
 | 
			
		||||
     *
 | 
			
		||||
     * The ::key-activated signal is emitted each time a key is
 | 
			
		||||
     * pressed in @context.
 | 
			
		||||
     */
 | 
			
		||||
    /*
 | 
			
		||||
    signals[KEY_ACTIVATED] =
 | 
			
		||||
        g_signal_new (I_("key-activated"),
 | 
			
		||||
                      G_TYPE_FROM_CLASS(gobject_class),
 | 
			
		||||
                      G_SIGNAL_RUN_LAST,
 | 
			
		||||
                      G_STRUCT_OFFSET(EekboardContextClass, key_activated),
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      NULL,
 | 
			
		||||
                      _eekboard_marshal_VOID__UINT_OBJECT_UINT,
 | 
			
		||||
                      G_TYPE_NONE,
 | 
			
		||||
                      3,
 | 
			
		||||
                      G_TYPE_UINT,
 | 
			
		||||
                      G_TYPE_OBJECT,
 | 
			
		||||
                      G_TYPE_UINT);
 | 
			
		||||
*/
 | 
			
		||||
    /**
 | 
			
		||||
     * EekboardContext::destroyed:
 | 
			
		||||
     * @context: an #EekboardContext
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,11 @@ struct _EekboardContextClass {
 | 
			
		||||
    void (*disabled)      (EekboardContext *self);
 | 
			
		||||
    void (*destroyed)     (EekboardContext *self);
 | 
			
		||||
 | 
			
		||||
    void (*key_activated) (EekboardContext *self,
 | 
			
		||||
                           guint            keycode,
 | 
			
		||||
                           EekSymbol       *symbol,
 | 
			
		||||
                           guint            modifiers);
 | 
			
		||||
 | 
			
		||||
    /*< private >*/
 | 
			
		||||
    /* padding */
 | 
			
		||||
    gpointer pdummy[24];
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,6 @@
 | 
			
		||||
#include "eekboard/key-emitter.h"
 | 
			
		||||
 | 
			
		||||
#include <gdk/gdk.h>
 | 
			
		||||
#include <X11/XKBlib.h>
 | 
			
		||||
 | 
			
		||||
#include "eekboard/eekboard-context-service.h"
 | 
			
		||||
 | 
			
		||||
@ -49,6 +48,26 @@ int send_virtual_keyboard_key(
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_fake_modifiers_events (SeatEmitter         *emitter,
 | 
			
		||||
                            EekModifierType      modifiers,
 | 
			
		||||
                            uint32_t             timestamp)
 | 
			
		||||
{
 | 
			
		||||
    (void)timestamp;
 | 
			
		||||
 | 
			
		||||
    uint32_t proto_modifiers = 0;
 | 
			
		||||
    if (modifiers & EEK_SHIFT_MASK) {
 | 
			
		||||
        proto_modifiers |= 1<<MOD_IDX_SHIFT;
 | 
			
		||||
    }
 | 
			
		||||
    if (modifiers & EEK_CONTROL_MASK) {
 | 
			
		||||
        proto_modifiers |= 1<<MOD_IDX_CTRL;
 | 
			
		||||
    }
 | 
			
		||||
    if (modifiers & EEK_MOD1_MASK) {
 | 
			
		||||
        proto_modifiers |= 1<<MOD_IDX_ALT;
 | 
			
		||||
    }
 | 
			
		||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, emitter->group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Finds the first key code for each modifier and saves it in modifier_keycodes */
 | 
			
		||||
static void
 | 
			
		||||
update_modifier_info (SeatEmitter *client)
 | 
			
		||||
@ -85,23 +104,30 @@ update_modifier_info (SeatEmitter *client)
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
send_fake_key (SeatEmitter *emitter,
 | 
			
		||||
               LevelKeyboard *keyboard,
 | 
			
		||||
               EekKeyboard *keyboard,
 | 
			
		||||
               guint    keycode,
 | 
			
		||||
               guint    keyboard_modifiers,
 | 
			
		||||
               gboolean pressed,
 | 
			
		||||
               uint32_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
    guint level = keyboard->level;
 | 
			
		||||
    uint32_t proto_modifiers = 0;
 | 
			
		||||
    guint level = eek_element_get_level(EEK_ELEMENT(keyboard));
 | 
			
		||||
    uint32_t group = (level / 2);
 | 
			
		||||
 | 
			
		||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, 0, 0, 0, group);
 | 
			
		||||
    if (keyboard_modifiers & EEK_SHIFT_MASK)
 | 
			
		||||
        proto_modifiers |= 1<<MOD_IDX_SHIFT;
 | 
			
		||||
 | 
			
		||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
 | 
			
		||||
    send_virtual_keyboard_key (emitter->virtual_keyboard, keycode - 8, (unsigned)pressed, timestamp);
 | 
			
		||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, 0, 0, 0, group);
 | 
			
		||||
    zwp_virtual_keyboard_v1_modifiers(emitter->virtual_keyboard, proto_modifiers, 0, 0, group);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
emit_key_activated (EekboardContextService *manager,
 | 
			
		||||
                    LevelKeyboard     *keyboard,
 | 
			
		||||
                    EekKeyboard     *keyboard,
 | 
			
		||||
                    guint            keycode,
 | 
			
		||||
                    EekSymbol       *symbol,
 | 
			
		||||
                    EekModifierType  modifiers,
 | 
			
		||||
                    gboolean pressed,
 | 
			
		||||
                    uint32_t timestamp)
 | 
			
		||||
{
 | 
			
		||||
@ -136,5 +162,5 @@ emit_key_activated (EekboardContextService *manager,
 | 
			
		||||
    emitter.virtual_keyboard = manager->virtual_keyboard;
 | 
			
		||||
    emitter.keymap = keyboard->keymap;
 | 
			
		||||
    update_modifier_info (&emitter);
 | 
			
		||||
    send_fake_key (&emitter, keyboard, keycode, pressed, timestamp);
 | 
			
		||||
    send_fake_key (&emitter, keyboard, keycode, modifiers, pressed, timestamp);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,9 @@ enum mod_indices {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
emit_key_activated (EekboardContextService *manager, LevelKeyboard *keyboard,
 | 
			
		||||
emit_key_activated (EekboardContextService *manager, EekKeyboard *keyboard,
 | 
			
		||||
                    guint            keycode,
 | 
			
		||||
                    EekSymbol       *symbol,
 | 
			
		||||
                    guint            modifiers,
 | 
			
		||||
                    gboolean pressed, uint32_t timestamp);
 | 
			
		||||
#endif // KEYEMITTER_H
 | 
			
		||||
 | 
			
		||||
@ -16,8 +16,7 @@ add_project_arguments(
 | 
			
		||||
    '-Werror=implicit-function-declaration',
 | 
			
		||||
    '-Werror=implicit-fallthrough=3',
 | 
			
		||||
    '-Werror=maybe-uninitialized',
 | 
			
		||||
    '-Werror=missing-field-initializers',
 | 
			
		||||
    '-Werror=incompatible-pointer-types',
 | 
			
		||||
#    '-Werror=missing-field-initializers', // fix eek-unicode-keysym-entries first
 | 
			
		||||
  ],
 | 
			
		||||
  language: 'c'
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										141
									
								
								src/float_ord.rs
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								src/float_ord.rs
									
									
									
									
									
								
							@ -1,141 +0,0 @@
 | 
			
		||||
//! Order floating point numbers, into this ordering:
 | 
			
		||||
//!
 | 
			
		||||
//!    NaN | -Infinity | x < 0 | -0 | +0 | x > 0 | +Infinity | NaN
 | 
			
		||||
 | 
			
		||||
/* Adapted from https://github.com/notriddle/rust-float-ord revision e995165f
 | 
			
		||||
 * maintained by Michael Howell <michael@notriddle.com>
 | 
			
		||||
 * licensed under MIT / Apache-2.0 licenses
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
extern crate core;
 | 
			
		||||
 | 
			
		||||
use ::float_ord::core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
 | 
			
		||||
use ::float_ord::core::hash::{Hash, Hasher};
 | 
			
		||||
use ::float_ord::core::mem::transmute;
 | 
			
		||||
 | 
			
		||||
/// A wrapper for floats, that implements total equality and ordering
 | 
			
		||||
/// and hashing.
 | 
			
		||||
#[derive(Clone, Copy)]
 | 
			
		||||
pub struct FloatOrd<T>(pub T);
 | 
			
		||||
 | 
			
		||||
macro_rules! float_ord_impl {
 | 
			
		||||
    ($f:ident, $i:ident, $n:expr) => {
 | 
			
		||||
        impl FloatOrd<$f> {
 | 
			
		||||
            fn convert(self) -> $i {
 | 
			
		||||
                let u = unsafe { transmute::<$f, $i>(self.0) };
 | 
			
		||||
                let bit = 1 << ($n - 1);
 | 
			
		||||
                if u & bit == 0 {
 | 
			
		||||
                    u | bit
 | 
			
		||||
                } else {
 | 
			
		||||
                    !u
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl PartialEq for FloatOrd<$f> {
 | 
			
		||||
            fn eq(&self, other: &Self) -> bool {
 | 
			
		||||
                self.convert() == other.convert()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl Eq for FloatOrd<$f> {}
 | 
			
		||||
        impl PartialOrd for FloatOrd<$f> {
 | 
			
		||||
            fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
 | 
			
		||||
                self.convert().partial_cmp(&other.convert())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl Ord for FloatOrd<$f> {
 | 
			
		||||
            fn cmp(&self, other: &Self) -> Ordering {
 | 
			
		||||
                self.convert().cmp(&other.convert())
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        impl Hash for FloatOrd<$f> {
 | 
			
		||||
            fn hash<H: Hasher>(&self, state: &mut H) {
 | 
			
		||||
                self.convert().hash(state);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
float_ord_impl!(f32, u32, 32);
 | 
			
		||||
float_ord_impl!(f64, u64, 64);
 | 
			
		||||
 | 
			
		||||
/// Sort a slice of floats.
 | 
			
		||||
///
 | 
			
		||||
/// # Allocation behavior
 | 
			
		||||
///
 | 
			
		||||
/// This routine uses a quicksort implementation that does not heap allocate.
 | 
			
		||||
///
 | 
			
		||||
/// # Example
 | 
			
		||||
///
 | 
			
		||||
/// ```
 | 
			
		||||
/// let mut v = [-5.0, 4.0, 1.0, -3.0, 2.0];
 | 
			
		||||
///
 | 
			
		||||
/// float_ord::sort(&mut v);
 | 
			
		||||
/// assert!(v == [-5.0, -3.0, 1.0, 2.0, 4.0]);
 | 
			
		||||
/// ```
 | 
			
		||||
#[allow(dead_code)]
 | 
			
		||||
pub fn sort<T>(v: &mut [T]) where FloatOrd<T>: Ord {
 | 
			
		||||
    let v_: &mut [FloatOrd<T>] = unsafe { transmute(v) };
 | 
			
		||||
    v_.sort_unstable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
    extern crate std;
 | 
			
		||||
 | 
			
		||||
    use self::std::collections::hash_map::DefaultHasher;
 | 
			
		||||
    use self::std::hash::{Hash, Hasher};
 | 
			
		||||
    use super::FloatOrd;
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_ord() {
 | 
			
		||||
        assert!(FloatOrd(1.0f64) < FloatOrd(2.0f64));
 | 
			
		||||
        assert!(FloatOrd(2.0f32) > FloatOrd(1.0f32));
 | 
			
		||||
        assert!(FloatOrd(1.0f64) == FloatOrd(1.0f64));
 | 
			
		||||
        assert!(FloatOrd(1.0f32) == FloatOrd(1.0f32));
 | 
			
		||||
        assert!(FloatOrd(0.0f64) > FloatOrd(-0.0f64));
 | 
			
		||||
        assert!(FloatOrd(0.0f32) > FloatOrd(-0.0f32));
 | 
			
		||||
        assert!(FloatOrd(::float_ord::core::f64::NAN) == FloatOrd(::float_ord::core::f64::NAN));
 | 
			
		||||
        assert!(FloatOrd(::float_ord::core::f32::NAN) == FloatOrd(::float_ord::core::f32::NAN));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f64::NAN) < FloatOrd(::float_ord::core::f64::NAN));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f32::NAN) < FloatOrd(::float_ord::core::f32::NAN));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f64::INFINITY) < FloatOrd(::float_ord::core::f64::INFINITY));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f32::INFINITY) < FloatOrd(::float_ord::core::f32::INFINITY));
 | 
			
		||||
        assert!(FloatOrd(::float_ord::core::f64::INFINITY) < FloatOrd(::float_ord::core::f64::NAN));
 | 
			
		||||
        assert!(FloatOrd(::float_ord::core::f32::INFINITY) < FloatOrd(::float_ord::core::f32::NAN));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f64::NAN) < FloatOrd(::float_ord::core::f64::INFINITY));
 | 
			
		||||
        assert!(FloatOrd(-::float_ord::core::f32::NAN) < FloatOrd(::float_ord::core::f32::INFINITY));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn hash<F: Hash>(f: F) -> u64 {
 | 
			
		||||
        let mut hasher = DefaultHasher::new();
 | 
			
		||||
        f.hash(&mut hasher);
 | 
			
		||||
        hasher.finish()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_hash() {
 | 
			
		||||
        assert_ne!(hash(FloatOrd(0.0f64)), hash(FloatOrd(-0.0f64)));
 | 
			
		||||
        assert_ne!(hash(FloatOrd(0.0f32)), hash(FloatOrd(-0.0f32)));
 | 
			
		||||
        assert_eq!(hash(FloatOrd(-0.0f64)), hash(FloatOrd(-0.0f64)));
 | 
			
		||||
        assert_eq!(hash(FloatOrd(0.0f32)), hash(FloatOrd(0.0f32)));
 | 
			
		||||
        assert_ne!(hash(FloatOrd(::float_ord::core::f64::NAN)), hash(FloatOrd(-::float_ord::core::f64::NAN)));
 | 
			
		||||
        assert_ne!(hash(FloatOrd(::float_ord::core::f32::NAN)), hash(FloatOrd(-::float_ord::core::f32::NAN)));
 | 
			
		||||
        assert_eq!(hash(FloatOrd(::float_ord::core::f64::NAN)), hash(FloatOrd(::float_ord::core::f64::NAN)));
 | 
			
		||||
        assert_eq!(hash(FloatOrd(-::float_ord::core::f32::NAN)), hash(FloatOrd(-::float_ord::core::f32::NAN)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_sort_nan() {
 | 
			
		||||
        let nan = ::float_ord::core::f64::NAN;
 | 
			
		||||
        let mut v = [-1.0, 5.0, 0.0, -0.0, nan, 1.5, nan, 3.7];
 | 
			
		||||
        super::sort(&mut v);
 | 
			
		||||
        assert!(v[0] == -1.0);
 | 
			
		||||
        assert!(v[1] == 0.0 && v[1].is_sign_negative());
 | 
			
		||||
        assert!(v[2] == 0.0 && !v[2].is_sign_negative());
 | 
			
		||||
        assert!(v[3] == 1.5);
 | 
			
		||||
        assert!(v[4] == 3.7);
 | 
			
		||||
        assert!(v[5] == 5.0);
 | 
			
		||||
        assert!(v[6].is_nan());
 | 
			
		||||
        assert!(v[7].is_nan());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,25 +0,0 @@
 | 
			
		||||
#ifndef __KEYBOARD_H
 | 
			
		||||
#define __KYBOARD_H
 | 
			
		||||
 | 
			
		||||
#include "stdbool.h"
 | 
			
		||||
#include "inttypes.h"
 | 
			
		||||
 | 
			
		||||
struct squeek_key;
 | 
			
		||||
 | 
			
		||||
struct squeek_key *squeek_key_new(uint32_t keycode);
 | 
			
		||||
void squeek_key_free(struct squeek_key *key);
 | 
			
		||||
void squeek_key_add_symbol(struct squeek_key* key,
 | 
			
		||||
                           const char *element_name,
 | 
			
		||||
                           const char *text, uint32_t keyval,
 | 
			
		||||
                           const char *label, const char *icon,
 | 
			
		||||
                           const char *tooltip);
 | 
			
		||||
uint32_t squeek_key_is_pressed(struct squeek_key *key);
 | 
			
		||||
void squeek_key_set_pressed(struct squeek_key *key, uint32_t pressed);
 | 
			
		||||
uint32_t squeek_key_is_locked(struct squeek_key *key);
 | 
			
		||||
void squeek_key_set_locked(struct squeek_key *key, uint32_t pressed);
 | 
			
		||||
uint32_t squeek_key_get_keycode(struct squeek_key *key);
 | 
			
		||||
void squeek_key_set_keycode(struct squeek_key *key, uint32_t keycode);
 | 
			
		||||
 | 
			
		||||
struct squeek_symbol *squeek_key_get_symbol(struct squeek_key* key);
 | 
			
		||||
const char* squeek_key_to_keymap_entry(const char *key_name, struct squeek_key *key);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										300
									
								
								src/keyboard.rs
									
									
									
									
									
								
							
							
						
						
									
										300
									
								
								src/keyboard.rs
									
									
									
									
									
								
							@ -1,300 +0,0 @@
 | 
			
		||||
use std::vec::Vec;
 | 
			
		||||
 | 
			
		||||
use super::symbol;
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    use ::util::c::{ as_cstr, into_cstring };
 | 
			
		||||
    
 | 
			
		||||
    use std::cell::RefCell;
 | 
			
		||||
    use std::ffi::CString;
 | 
			
		||||
    use std::os::raw::c_char;
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
    use std::rc::Rc;
 | 
			
		||||
 | 
			
		||||
    // traits
 | 
			
		||||
    
 | 
			
		||||
    use std::borrow::ToOwned;
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    // The following defined in C
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    extern "C" {
 | 
			
		||||
        fn eek_keysym_from_name(name: *const c_char) -> u32;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// The wrapped structure for KeyState suitable for handling in C
 | 
			
		||||
    /// Since C doesn't respect borrowing rules,
 | 
			
		||||
    /// RefCell will enforce them dynamically (only 1 writer/many readers)
 | 
			
		||||
    /// Rc is implied and will ensure timely dropping
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    pub struct CKeyState(*const RefCell<KeyState>);
 | 
			
		||||
    
 | 
			
		||||
    impl Clone for CKeyState {
 | 
			
		||||
        fn clone(&self) -> Self {
 | 
			
		||||
            CKeyState(self.0.clone())
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    impl CKeyState {
 | 
			
		||||
        pub fn wrap(state: Rc<RefCell<KeyState>>) -> CKeyState {
 | 
			
		||||
            CKeyState(Rc::into_raw(state))
 | 
			
		||||
        }
 | 
			
		||||
        pub fn unwrap(self) -> Rc<RefCell<KeyState>> {
 | 
			
		||||
            unsafe { Rc::from_raw(self.0) }
 | 
			
		||||
        }
 | 
			
		||||
        fn to_owned(self) -> KeyState {
 | 
			
		||||
            let rc = self.unwrap();
 | 
			
		||||
            let state = rc.borrow().to_owned();
 | 
			
		||||
            Rc::into_raw(rc); // Prevent dropping
 | 
			
		||||
            state
 | 
			
		||||
        }
 | 
			
		||||
        fn borrow_mut<F, T>(self, f: F) -> T where F: FnOnce(&mut KeyState) -> T {
 | 
			
		||||
            let rc = self.unwrap();
 | 
			
		||||
            let ret = {
 | 
			
		||||
                let mut state = rc.borrow_mut();
 | 
			
		||||
                f(&mut state)
 | 
			
		||||
            };
 | 
			
		||||
            Rc::into_raw(rc); // Prevent dropping
 | 
			
		||||
            ret
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // TODO: unwrapping
 | 
			
		||||
 | 
			
		||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
			
		||||
    
 | 
			
		||||
    // TODO: this will receive data from the filesystem,
 | 
			
		||||
    // so it should handle garbled strings in the future
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_new(keycode: u32) -> CKeyState {
 | 
			
		||||
        let state: Rc<RefCell<KeyState>> = Rc::new(RefCell::new(
 | 
			
		||||
            KeyState {
 | 
			
		||||
                pressed: false,
 | 
			
		||||
                locked: false,
 | 
			
		||||
                keycode: keycode,
 | 
			
		||||
                symbol: None,
 | 
			
		||||
            }
 | 
			
		||||
        ));
 | 
			
		||||
        CKeyState::wrap(state)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_free(key: CKeyState) {
 | 
			
		||||
        key.unwrap(); // reference dropped
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_is_pressed(key: CKeyState) -> u32 {
 | 
			
		||||
        //let key = unsafe { Rc::from_raw(key.0) };
 | 
			
		||||
        return key.to_owned().pressed as u32;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_set_pressed(key: CKeyState, pressed: u32) {
 | 
			
		||||
        key.borrow_mut(|key| key.pressed = pressed != 0);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_is_locked(key: CKeyState) -> u32 {
 | 
			
		||||
        return key.to_owned().locked as u32;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_set_locked(key: CKeyState, locked: u32) {
 | 
			
		||||
        key.borrow_mut(|key| key.locked = locked != 0);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_get_keycode(key: CKeyState) -> u32 {
 | 
			
		||||
        return key.to_owned().keycode as u32;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_set_keycode(key: CKeyState, code: u32) {
 | 
			
		||||
        key.borrow_mut(|key| key.keycode = code);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // TODO: this will receive data from the filesystem,
 | 
			
		||||
    // so it should handle garbled strings in the future
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_add_symbol(
 | 
			
		||||
        key: CKeyState,
 | 
			
		||||
        element: *const c_char,
 | 
			
		||||
        text_raw: *const c_char, keyval: u32,
 | 
			
		||||
        label: *const c_char, icon: *const c_char,
 | 
			
		||||
        tooltip: *const c_char,
 | 
			
		||||
    ) {
 | 
			
		||||
        let element = as_cstr(&element)
 | 
			
		||||
            .expect("Missing element name");
 | 
			
		||||
 | 
			
		||||
        let text = into_cstring(text_raw)
 | 
			
		||||
            .unwrap_or_else(|e| {
 | 
			
		||||
                eprintln!("Text unreadable: {}", e);
 | 
			
		||||
                None
 | 
			
		||||
            })
 | 
			
		||||
            .and_then(|text| {
 | 
			
		||||
                if text.as_bytes() == b"" {
 | 
			
		||||
                    None
 | 
			
		||||
                } else {
 | 
			
		||||
                    Some(text)
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        let icon = into_cstring(icon)
 | 
			
		||||
            .unwrap_or_else(|e| {
 | 
			
		||||
                eprintln!("Icon name unreadable: {}", e);
 | 
			
		||||
                None
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        use symbol::*;
 | 
			
		||||
        // Only read label if there's no icon
 | 
			
		||||
        let label = match icon {
 | 
			
		||||
            Some(icon) => Label::IconName(icon),
 | 
			
		||||
            None => Label::Text(
 | 
			
		||||
                into_cstring(label)
 | 
			
		||||
                    .unwrap_or_else(|e| {
 | 
			
		||||
                        eprintln!("Label unreadable: {}", e);
 | 
			
		||||
                        Some(CString::new(" ").unwrap())
 | 
			
		||||
                    })
 | 
			
		||||
                    .unwrap_or_else(|| {
 | 
			
		||||
                        eprintln!("Label missing");
 | 
			
		||||
                        CString::new(" ").unwrap()
 | 
			
		||||
                    })
 | 
			
		||||
            ),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let tooltip = into_cstring(tooltip)
 | 
			
		||||
            .unwrap_or_else(|e| {
 | 
			
		||||
                eprintln!("Tooltip unreadable: {}", e);
 | 
			
		||||
                None
 | 
			
		||||
            });
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        key.borrow_mut(|key| {
 | 
			
		||||
            if let Some(_) = key.symbol {
 | 
			
		||||
                eprintln!("Key {:?} already has a symbol defined", text);
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            key.symbol = Some(match element.to_bytes() {
 | 
			
		||||
                b"symbol" => Symbol {
 | 
			
		||||
                    action: Action::Submit {
 | 
			
		||||
                        text: text,
 | 
			
		||||
                        keys: Vec::new(),
 | 
			
		||||
                    },
 | 
			
		||||
                    label: label,
 | 
			
		||||
                    tooltip: tooltip,
 | 
			
		||||
                },
 | 
			
		||||
                _ => panic!("unsupported element type {:?}", element),
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_get_symbol(key: CKeyState) -> *const symbol::Symbol {
 | 
			
		||||
        key.borrow_mut(|key| {
 | 
			
		||||
            match key.symbol {
 | 
			
		||||
                // This pointer stays after the function exits,
 | 
			
		||||
                // so it must reference borrowed data and not any copy
 | 
			
		||||
                Some(ref symbol) => symbol as *const symbol::Symbol,
 | 
			
		||||
                None => ptr::null(),
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_to_keymap_entry(
 | 
			
		||||
        key_name: *const c_char,
 | 
			
		||||
        key: CKeyState,
 | 
			
		||||
    ) -> *const c_char {
 | 
			
		||||
        let key_name = as_cstr(&key_name)
 | 
			
		||||
            .expect("Missing key name")
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .expect("Bad key name");
 | 
			
		||||
 | 
			
		||||
        let symbol_name = match key.to_owned().symbol {
 | 
			
		||||
            Some(ref symbol) => match &symbol.action {
 | 
			
		||||
                symbol::Action::Submit { text: Some(text), .. } => {
 | 
			
		||||
                    Some(
 | 
			
		||||
                        text.clone()
 | 
			
		||||
                            .into_string().expect("Bad symbol")
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                _ => None
 | 
			
		||||
            },
 | 
			
		||||
            None => {
 | 
			
		||||
                eprintln!("Key {} has no symbol", key_name);
 | 
			
		||||
                None
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let inner = match symbol_name {
 | 
			
		||||
            Some(name) => format!("[ {} ]", name),
 | 
			
		||||
            _ => format!("[ ]"),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        CString::new(format!("        key <{}> {{ {} }};\n", key_name, inner))
 | 
			
		||||
            .expect("Couldn't convert string")
 | 
			
		||||
            .into_raw()
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_key_get_action_name(
 | 
			
		||||
        key_name: *const c_char,
 | 
			
		||||
        key: CKeyState,
 | 
			
		||||
    ) -> *const c_char {
 | 
			
		||||
        let key_name = as_cstr(&key_name)
 | 
			
		||||
            .expect("Missing key name")
 | 
			
		||||
            .to_str()
 | 
			
		||||
            .expect("Bad key name");
 | 
			
		||||
 | 
			
		||||
        let symbol_name = match key.to_owned().symbol {
 | 
			
		||||
            Some(ref symbol) => match &symbol.action {
 | 
			
		||||
                symbol::Action::Submit { text: Some(text), .. } => {
 | 
			
		||||
                    Some(
 | 
			
		||||
                        text.clone()
 | 
			
		||||
                            .into_string().expect("Bad symbol")
 | 
			
		||||
                    )
 | 
			
		||||
                },
 | 
			
		||||
                _ => None
 | 
			
		||||
            },
 | 
			
		||||
            None => {
 | 
			
		||||
                eprintln!("Key {} has no symbol", key_name);
 | 
			
		||||
                None
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        let inner = match symbol_name {
 | 
			
		||||
            Some(name) => format!("[ {} ]", name),
 | 
			
		||||
            _ => format!("[ ]"),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        CString::new(format!("        key <{}> {{ {} }};\n", key_name, inner))
 | 
			
		||||
            .expect("Couldn't convert string")
 | 
			
		||||
            .into_raw()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct KeyState {
 | 
			
		||||
    pub pressed: bool,
 | 
			
		||||
    pub locked: bool,
 | 
			
		||||
    pub keycode: u32,
 | 
			
		||||
    // TODO: remove the optionality of a symbol
 | 
			
		||||
    pub symbol: Option<symbol::Symbol>,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										78
									
								
								src/layout.h
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								src/layout.h
									
									
									
									
									
								
							@ -1,78 +0,0 @@
 | 
			
		||||
#ifndef __LAYOUT_H
 | 
			
		||||
#define __LAYOUT_H
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
#include "eek/eek-element.h"
 | 
			
		||||
#include "src/keyboard.h"
 | 
			
		||||
 | 
			
		||||
struct squeek_button;
 | 
			
		||||
struct squeek_row;
 | 
			
		||||
struct squeek_view;
 | 
			
		||||
 | 
			
		||||
struct squeek_row *squeek_row_new(int32_t angle);
 | 
			
		||||
struct squeek_button *squeek_row_create_button (struct squeek_row *row,
 | 
			
		||||
                                          guint keycode, guint oref);
 | 
			
		||||
struct squeek_button *squeek_row_create_button_with_state(struct squeek_row *row,
 | 
			
		||||
                                    struct squeek_button *source);
 | 
			
		||||
void squeek_row_set_angle(struct squeek_row *row, int32_t angle);
 | 
			
		||||
int32_t squeek_row_get_angle(const struct squeek_row*);
 | 
			
		||||
 | 
			
		||||
EekBounds squeek_row_get_bounds(const struct squeek_row*);
 | 
			
		||||
void squeek_row_set_bounds(struct squeek_row* row, EekBounds bounds);
 | 
			
		||||
 | 
			
		||||
uint32_t squeek_row_contains(struct squeek_row*, struct squeek_button *button);
 | 
			
		||||
 | 
			
		||||
struct button_place squeek_view_find_key(struct squeek_view*, struct squeek_key *state);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef void (*ButtonCallback) (struct squeek_button *button, gpointer user_data);
 | 
			
		||||
void squeek_row_foreach(struct squeek_row*,
 | 
			
		||||
                            ButtonCallback   callback,
 | 
			
		||||
                            gpointer      user_data);
 | 
			
		||||
 | 
			
		||||
void squeek_row_free(struct squeek_row*);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
struct squeek_button *squeek_buttons_find_by_position(
 | 
			
		||||
    const struct squeek_buttons *buttons,
 | 
			
		||||
    double x, double y,
 | 
			
		||||
    double origin_x, double origin_y,
 | 
			
		||||
    double angle);
 | 
			
		||||
void squeek_buttons_add(struct squeek_buttons*, const struct squeek_button* button);
 | 
			
		||||
void squeek_buttons_remove_key(struct squeek_buttons*, const struct squeek_key* key);
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
struct squeek_button *squeek_button_new(uint32_t keycode, uint32_t oref);
 | 
			
		||||
struct squeek_button *squeek_button_new_with_state(const struct squeek_button* source);
 | 
			
		||||
uint32_t squeek_button_get_oref(const struct squeek_button*);
 | 
			
		||||
EekBounds squeek_button_get_bounds(const struct squeek_button*);
 | 
			
		||||
void squeek_button_set_bounds(struct squeek_button* button, EekBounds bounds);
 | 
			
		||||
 | 
			
		||||
struct squeek_symbol *squeek_button_get_symbol (
 | 
			
		||||
    const struct squeek_button *button);
 | 
			
		||||
struct squeek_key *squeek_button_get_key(const struct squeek_button*);
 | 
			
		||||
uint32_t *squeek_button_has_key(const struct squeek_button* button,
 | 
			
		||||
                                const struct squeek_key *key);
 | 
			
		||||
void squeek_button_print(const struct squeek_button* button);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct squeek_view *squeek_view_new(EekBounds bounds);
 | 
			
		||||
struct squeek_row *squeek_view_create_row(struct squeek_view *, int32_t angle);
 | 
			
		||||
EekBounds squeek_view_get_bounds(const struct squeek_view*);
 | 
			
		||||
void squeek_view_set_bounds(const struct squeek_view*, EekBounds bounds);
 | 
			
		||||
 | 
			
		||||
typedef void (*RowCallback) (struct squeek_row *row, gpointer user_data);
 | 
			
		||||
void squeek_view_foreach(struct squeek_view*,
 | 
			
		||||
                            RowCallback   callback,
 | 
			
		||||
                            gpointer      user_data);
 | 
			
		||||
 | 
			
		||||
struct squeek_row *squeek_view_get_row(struct squeek_view *view,
 | 
			
		||||
                                       struct squeek_button *button);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
squeek_view_place_contents(struct squeek_view *view, LevelKeyboard *keyboard);
 | 
			
		||||
 | 
			
		||||
struct squeek_button *squeek_view_find_button_by_position(struct squeek_view *view, EekPoint point);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										764
									
								
								src/layout.rs
									
									
									
									
									
								
							
							
						
						
									
										764
									
								
								src/layout.rs
									
									
									
									
									
								
							@ -1,764 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Layout-related data.
 | 
			
		||||
 * 
 | 
			
		||||
 * The `View` contains `Row`s and each `Row` contains `Button`s.
 | 
			
		||||
 * They carry data relevant to their positioning only,
 | 
			
		||||
 * except the Button, which also carries some data
 | 
			
		||||
 * about its appearance and function.
 | 
			
		||||
 * 
 | 
			
		||||
 * The layout is determined bottom-up, by measuring `Button` sizes,
 | 
			
		||||
 * deriving `Row` sizes from them, and then centering them within the `View`.
 | 
			
		||||
 * 
 | 
			
		||||
 * That makes the `View` position immutable,
 | 
			
		||||
 * and therefore different than the other positions.
 | 
			
		||||
 * 
 | 
			
		||||
 * Note that it might be a better idea
 | 
			
		||||
 * to make `View` position depend on its contents,
 | 
			
		||||
 * and let the renderer scale and center it within the widget.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
use std::cell::RefCell;
 | 
			
		||||
use std::rc::Rc;
 | 
			
		||||
use std::vec::Vec;
 | 
			
		||||
 | 
			
		||||
use ::keyboard::*;
 | 
			
		||||
use ::float_ord::FloatOrd;
 | 
			
		||||
use ::symbol::*;
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
 | 
			
		||||
    use std::os::raw::c_void;
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
 | 
			
		||||
    // The following defined in C
 | 
			
		||||
 | 
			
		||||
    #[repr(transparent)]
 | 
			
		||||
    pub struct UserData(*const c_void);
 | 
			
		||||
    
 | 
			
		||||
    /// The index in the relevant outline table
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    #[derive(Clone, Debug)]
 | 
			
		||||
    pub struct OutlineRef(u32);
 | 
			
		||||
 | 
			
		||||
    /// Defined in eek-types.h
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    #[derive(Clone, Debug)]
 | 
			
		||||
    pub struct Point {
 | 
			
		||||
        pub x: f64,
 | 
			
		||||
        pub y: f64,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Defined in eek-types.h
 | 
			
		||||
    #[repr(C)]
 | 
			
		||||
    #[derive(Clone, Debug)]
 | 
			
		||||
    pub struct Bounds {
 | 
			
		||||
        pub x: f64,
 | 
			
		||||
        pub y: f64,
 | 
			
		||||
        pub width: f64,
 | 
			
		||||
        pub height: f64
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    impl Bounds {
 | 
			
		||||
        pub fn zero() -> Bounds {
 | 
			
		||||
            Bounds { x: 0f64, y: 0f64, width: 0f64, height: 0f64 }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    type ButtonCallback = unsafe extern "C" fn(button: *mut ::layout::Button, data: *mut UserData);
 | 
			
		||||
    type RowCallback = unsafe extern "C" fn(row: *mut ::layout::Row, data: *mut UserData);
 | 
			
		||||
 | 
			
		||||
    // The following defined in Rust. TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_view_new(bounds: Bounds) -> *mut ::layout::View {
 | 
			
		||||
        Box::into_raw(Box::new(::layout::View {
 | 
			
		||||
            rows: Vec::new(),
 | 
			
		||||
            bounds: bounds,
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_view_get_bounds(view: *const ::layout::View) -> Bounds {
 | 
			
		||||
        unsafe { &*view }.bounds.clone()
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_view_set_bounds(view: *mut ::layout::View, bounds: Bounds) {
 | 
			
		||||
        unsafe { &mut *view }.bounds = bounds;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Places a row into the view and returns a reference to it
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_view_create_row(
 | 
			
		||||
        view: *mut ::layout::View,
 | 
			
		||||
        angle: i32,
 | 
			
		||||
    ) -> *mut ::layout::Row {
 | 
			
		||||
        let view = unsafe { &mut *view };
 | 
			
		||||
 | 
			
		||||
        view.rows.push(Box::new(::layout::Row::new(angle)));
 | 
			
		||||
        // Return the reference directly instead of a Box, it's not on the stack
 | 
			
		||||
        // It will live as long as the Vec
 | 
			
		||||
        let last_idx = view.rows.len() - 1;
 | 
			
		||||
        // Caution: Box can't be returned directly,
 | 
			
		||||
        // so returning a reference to its innards
 | 
			
		||||
        view.rows[last_idx].as_mut() as *mut ::layout::Row
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_view_foreach(
 | 
			
		||||
        view: *mut ::layout::View,
 | 
			
		||||
        callback: RowCallback,
 | 
			
		||||
        data: *mut UserData,
 | 
			
		||||
    ) {
 | 
			
		||||
        let view = unsafe { &mut *view };
 | 
			
		||||
        for row in view.rows.iter_mut() {
 | 
			
		||||
            let row = row.as_mut() as *mut ::layout::Row;
 | 
			
		||||
            unsafe { callback(row, data) };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_new(angle: i32) -> *mut ::layout::Row {
 | 
			
		||||
        Box::into_raw(Box::new(::layout::Row::new(angle)))
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Places a button into the row and returns a reference to it
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_create_button(
 | 
			
		||||
        row: *mut ::layout::Row,
 | 
			
		||||
        keycode: u32, oref: u32
 | 
			
		||||
    ) -> *mut ::layout::Button {
 | 
			
		||||
        let row = unsafe { &mut *row };
 | 
			
		||||
        let state: Rc<RefCell<::keyboard::KeyState>> = Rc::new(RefCell::new(
 | 
			
		||||
            ::keyboard::KeyState {
 | 
			
		||||
                pressed: false,
 | 
			
		||||
                locked: false,
 | 
			
		||||
                keycode: keycode,
 | 
			
		||||
                symbol: None,
 | 
			
		||||
            }
 | 
			
		||||
        ));
 | 
			
		||||
        row.buttons.push(Box::new(::layout::Button {
 | 
			
		||||
            oref: OutlineRef(oref),
 | 
			
		||||
            bounds: None,
 | 
			
		||||
            state: state,
 | 
			
		||||
        }));
 | 
			
		||||
        // Return the reference directly instead of a Box, it's not on the stack
 | 
			
		||||
        // It will live as long as the Vec
 | 
			
		||||
        let last_idx = row.buttons.len() - 1;
 | 
			
		||||
        // Caution: Box can't be returned directly,
 | 
			
		||||
        // so returning a reference to its innards
 | 
			
		||||
        row.buttons[last_idx].as_mut() as *mut ::layout::Button
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Places a button into the row, copying its state,
 | 
			
		||||
    /// and returns a reference to it
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_create_button_with_state(
 | 
			
		||||
        row: *mut ::layout::Row,
 | 
			
		||||
        button: *const ::layout::Button,
 | 
			
		||||
    ) -> *mut ::layout::Button {
 | 
			
		||||
        let row = unsafe { &mut *row };
 | 
			
		||||
        let source = unsafe { &*button };
 | 
			
		||||
        row.buttons.push(Box::new(source.clone()));
 | 
			
		||||
        // Return the reference directly instead of a Box, it's not on the stack
 | 
			
		||||
        // It will live as long as the Vec
 | 
			
		||||
        let last_idx = row.buttons.len() - 1;
 | 
			
		||||
        // Caution: Box can't be returned directly,
 | 
			
		||||
        // so returning a reference to its innards directly
 | 
			
		||||
        row.buttons[last_idx].as_mut() as *mut ::layout::Button
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_set_angle(row: *mut ::layout::Row, angle: i32) {
 | 
			
		||||
        let row = unsafe { &mut *row };
 | 
			
		||||
        row.angle = angle;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_get_angle(row: *const ::layout::Row) -> i32 {
 | 
			
		||||
        let row = unsafe { &*row };
 | 
			
		||||
        row.angle
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_get_bounds(row: *const ::layout::Row) -> Bounds {
 | 
			
		||||
        let row = unsafe { &*row };
 | 
			
		||||
        match &row.bounds {
 | 
			
		||||
            Some(bounds) => bounds.clone(),
 | 
			
		||||
            None => panic!("Row doesn't have any bounds yet"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Set bounds by consuming the value
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_set_bounds(row: *mut ::layout::Row, bounds: Bounds) {
 | 
			
		||||
        let row = unsafe { &mut *row };
 | 
			
		||||
        row.bounds = Some(bounds);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_foreach(
 | 
			
		||||
        row: *mut ::layout::Row,
 | 
			
		||||
        callback: ButtonCallback,
 | 
			
		||||
        data: *mut UserData,
 | 
			
		||||
    ) {
 | 
			
		||||
        let row = unsafe { &mut *row };
 | 
			
		||||
        for button in row.buttons.iter_mut() {
 | 
			
		||||
            let button = button.as_mut() as *mut ::layout::Button;
 | 
			
		||||
            unsafe { callback(button, data) };
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_row_free(row: *mut ::layout::Row) {
 | 
			
		||||
        unsafe { Box::from_raw(row) }; // gets dropped
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_new(keycode: u32, oref: u32) -> *mut ::layout::Button {
 | 
			
		||||
        let state: Rc<RefCell<::keyboard::KeyState>> = Rc::new(RefCell::new(
 | 
			
		||||
            ::keyboard::KeyState {
 | 
			
		||||
                pressed: false,
 | 
			
		||||
                locked: false,
 | 
			
		||||
                keycode: keycode,
 | 
			
		||||
                symbol: None,
 | 
			
		||||
            }
 | 
			
		||||
        ));
 | 
			
		||||
        Box::into_raw(Box::new(::layout::Button {
 | 
			
		||||
            oref: OutlineRef(oref),
 | 
			
		||||
            bounds: None,
 | 
			
		||||
            state: state,
 | 
			
		||||
        }))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_new_with_state(source: *mut ::layout::Button) -> *mut ::layout::Button {
 | 
			
		||||
        let source = unsafe { &*source };
 | 
			
		||||
        let button = Box::new(source.clone());
 | 
			
		||||
        Box::into_raw(button)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_get_oref(button: *const ::layout::Button) -> u32 {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        button.oref.0
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Bounds transparently mapped to C, therefore no pointer needed
 | 
			
		||||
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_get_bounds(button: *const ::layout::Button) -> Bounds {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        match &button.bounds {
 | 
			
		||||
            Some(bounds) => bounds.clone(),
 | 
			
		||||
            None => panic!("Button doesn't have any bounds yet"),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Set bounds by consuming the value
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_set_bounds(button: *mut ::layout::Button, bounds: Bounds) {
 | 
			
		||||
        let button = unsafe { &mut *button };
 | 
			
		||||
        button.bounds = Some(bounds);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Borrow a new reference to key state. Doesn't need freeing
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_get_key(
 | 
			
		||||
        button: *const ::layout::Button
 | 
			
		||||
    ) -> ::keyboard::c::CKeyState {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        ::keyboard::c::CKeyState::wrap(button.state.clone())
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Really should just return the label
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_get_symbol(
 | 
			
		||||
        button: *const ::layout::Button,
 | 
			
		||||
    ) -> *const Symbol {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        let state = button.state.borrow();
 | 
			
		||||
        match state.symbol {
 | 
			
		||||
            Some(ref symbol) => symbol as *const Symbol,
 | 
			
		||||
            None => ptr::null(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_has_key(
 | 
			
		||||
        button: *const ::layout::Button,
 | 
			
		||||
        state: ::keyboard::c::CKeyState,
 | 
			
		||||
    ) -> u32 {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        let state = state.unwrap();
 | 
			
		||||
        let equal = Rc::ptr_eq(&button.state, &state);
 | 
			
		||||
        Rc::into_raw(state); // Prevent dropping
 | 
			
		||||
        equal as u32
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_button_print(button: *const ::layout::Button) {
 | 
			
		||||
        let button = unsafe { &*button };
 | 
			
		||||
        println!("{:?}", button);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Entry points for more complex procedures and algoithms which span multiple modules
 | 
			
		||||
    pub mod procedures {
 | 
			
		||||
        use super::*;
 | 
			
		||||
        
 | 
			
		||||
        #[repr(transparent)]
 | 
			
		||||
        pub struct LevelKeyboard(*const c_void);
 | 
			
		||||
        
 | 
			
		||||
        #[repr(C)]
 | 
			
		||||
        #[derive(PartialEq, Debug)]
 | 
			
		||||
        pub struct ButtonPlace {
 | 
			
		||||
            row: *const Row,
 | 
			
		||||
            button: *const Button,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
        extern "C" {
 | 
			
		||||
            fn eek_get_outline_size(
 | 
			
		||||
                keyboard: *const LevelKeyboard,
 | 
			
		||||
                outline: u32
 | 
			
		||||
            ) -> Bounds;
 | 
			
		||||
 | 
			
		||||
            /// Checks if point falls within bounds,
 | 
			
		||||
            /// which are relative to origin and rotated by angle (I think)
 | 
			
		||||
            pub fn eek_are_bounds_inside (bounds: Bounds,
 | 
			
		||||
                point: Point,
 | 
			
		||||
                origin: Point,
 | 
			
		||||
                angle: i32
 | 
			
		||||
            ) -> u32;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        fn squeek_buttons_get_outlines(
 | 
			
		||||
            buttons: &Vec<Box<Button>>,
 | 
			
		||||
            keyboard: *const LevelKeyboard,
 | 
			
		||||
        ) -> Vec<Bounds> {
 | 
			
		||||
            buttons.iter().map(|button| {
 | 
			
		||||
                unsafe { eek_get_outline_size(keyboard, button.oref.0) }
 | 
			
		||||
            }).collect()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// Places each button in order, starting from 0 on the left,
 | 
			
		||||
        /// keeping the spacing.
 | 
			
		||||
        /// Sizes each button according to outline dimensions.
 | 
			
		||||
        /// Places each row in order, starting from 0 on the top,
 | 
			
		||||
        /// keeping the spacing.
 | 
			
		||||
        /// Sets button and row sizes according to their contents.
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_view_place_contents(
 | 
			
		||||
            view: *mut ::layout::View,
 | 
			
		||||
            keyboard: *const LevelKeyboard, // source of outlines
 | 
			
		||||
        ) {
 | 
			
		||||
            let view = unsafe { &mut *view };
 | 
			
		||||
            
 | 
			
		||||
            let sizes: Vec<Vec<Bounds>> = view.rows.iter().map(|row|
 | 
			
		||||
                squeek_buttons_get_outlines(&row.buttons, keyboard)
 | 
			
		||||
            ).collect();
 | 
			
		||||
 | 
			
		||||
            view.place_buttons_with_sizes(sizes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        fn squeek_row_contains(row: &Row, needle: *const Button) -> bool {
 | 
			
		||||
            row.buttons.iter().position(
 | 
			
		||||
                // TODO: wrap Button properly in Rc; this comparison is unreliable
 | 
			
		||||
                |button| button.as_ref() as *const ::layout::Button == needle
 | 
			
		||||
            ).is_some()
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_view_get_row(
 | 
			
		||||
            view: *mut View,
 | 
			
		||||
            needle: *const ::layout::Button,
 | 
			
		||||
        ) -> *mut Row {
 | 
			
		||||
            let view = unsafe { &mut *view };
 | 
			
		||||
            let result = view.rows.iter_mut().find(|row| {
 | 
			
		||||
                squeek_row_contains(row, needle)
 | 
			
		||||
            });
 | 
			
		||||
            match result {
 | 
			
		||||
                Some(row) => row.as_mut() as *mut Row,
 | 
			
		||||
                None => ptr::null_mut(),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_view_find_key(
 | 
			
		||||
            view: *const View,
 | 
			
		||||
            needle: ::keyboard::c::CKeyState,
 | 
			
		||||
        ) -> ButtonPlace {
 | 
			
		||||
            let view = unsafe { &*view };
 | 
			
		||||
            let state = needle.unwrap();
 | 
			
		||||
            
 | 
			
		||||
            let paths = ::layout::procedures::find_key_paths(view, &state);
 | 
			
		||||
 | 
			
		||||
            // Iterators used up, can turn the reference back into pointer
 | 
			
		||||
            Rc::into_raw(state);
 | 
			
		||||
 | 
			
		||||
            // Can only return 1 entry back to C
 | 
			
		||||
            let (row, button) = match paths.get(0) {
 | 
			
		||||
                Some((row, button)) => (
 | 
			
		||||
                    row.as_ref() as *const Row,
 | 
			
		||||
                    button.as_ref() as *const Button,
 | 
			
		||||
                ),
 | 
			
		||||
                None => ( ptr::null(), ptr::null() ),
 | 
			
		||||
            };
 | 
			
		||||
            ButtonPlace { row, button }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #[no_mangle]
 | 
			
		||||
        pub extern "C"
 | 
			
		||||
        fn squeek_view_find_button_by_position(
 | 
			
		||||
            view: *mut View, point: Point
 | 
			
		||||
        ) -> *mut Button {
 | 
			
		||||
            let view = unsafe { &mut *view };
 | 
			
		||||
            let result = view.find_button_by_position(point);
 | 
			
		||||
            match result {
 | 
			
		||||
                Some(button) => button.as_mut() as *mut Button,
 | 
			
		||||
                None => ptr::null_mut(),
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #[cfg(test)]
 | 
			
		||||
        mod test {
 | 
			
		||||
            use super::*;
 | 
			
		||||
 | 
			
		||||
            #[test]
 | 
			
		||||
            fn row_has_button() {
 | 
			
		||||
                let mut row = Row::new(0);
 | 
			
		||||
                let button = squeek_row_create_button(&mut row as *mut Row, 0, 0);
 | 
			
		||||
                assert_eq!(squeek_row_contains(&row, button), true);
 | 
			
		||||
                let shared_button = squeek_row_create_button_with_state(
 | 
			
		||||
                    &mut row as *mut Row,
 | 
			
		||||
                    button
 | 
			
		||||
                );
 | 
			
		||||
                assert_eq!(squeek_row_contains(&row, shared_button), true);
 | 
			
		||||
                let row = Row::new(0);
 | 
			
		||||
                assert_eq!(squeek_row_contains(&row, button), false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            #[test]
 | 
			
		||||
            fn view_has_button() {
 | 
			
		||||
                let state = Rc::new(RefCell::new(::keyboard::KeyState {
 | 
			
		||||
                    pressed: false,
 | 
			
		||||
                    locked: false,
 | 
			
		||||
                    keycode: 0,
 | 
			
		||||
                    symbol: None,
 | 
			
		||||
                }));
 | 
			
		||||
                let state_clone = ::keyboard::c::CKeyState::wrap(state.clone());
 | 
			
		||||
 | 
			
		||||
                let button = Box::new(Button {
 | 
			
		||||
                    oref: OutlineRef(0),
 | 
			
		||||
                    bounds: None,
 | 
			
		||||
                    state: state,
 | 
			
		||||
                });
 | 
			
		||||
                let button_ptr = button.as_ref() as *const Button;
 | 
			
		||||
                
 | 
			
		||||
                let row = Box::new(Row {
 | 
			
		||||
                    buttons: vec!(button),
 | 
			
		||||
                    angle: 0,
 | 
			
		||||
                    bounds: None
 | 
			
		||||
                });
 | 
			
		||||
                let row_ptr = row.as_ref() as *const Row;
 | 
			
		||||
 | 
			
		||||
                let view = View {
 | 
			
		||||
                    bounds: Bounds {
 | 
			
		||||
                        x: 0f64, y: 0f64,
 | 
			
		||||
                        width: 0f64, height: 0f64
 | 
			
		||||
                    },
 | 
			
		||||
                    rows: vec!(row),
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                assert_eq!(
 | 
			
		||||
                    squeek_view_find_key(
 | 
			
		||||
                        &view as *const View,
 | 
			
		||||
                        state_clone.clone(),
 | 
			
		||||
                    ),
 | 
			
		||||
                    ButtonPlace {
 | 
			
		||||
                        row: row_ptr,
 | 
			
		||||
                        button: button_ptr,
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                let view = View {
 | 
			
		||||
                    bounds: Bounds {
 | 
			
		||||
                        x: 0f64, y: 0f64,
 | 
			
		||||
                        width: 0f64, height: 0f64
 | 
			
		||||
                    },
 | 
			
		||||
                    rows: Vec::new(),
 | 
			
		||||
                };
 | 
			
		||||
                assert_eq!(
 | 
			
		||||
                    squeek_view_find_key(
 | 
			
		||||
                        &view as *const View,
 | 
			
		||||
                        state_clone.clone()
 | 
			
		||||
                    ),
 | 
			
		||||
                    ButtonPlace {
 | 
			
		||||
                        row: ptr::null(),
 | 
			
		||||
                        button: ptr::null(),
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(test)]
 | 
			
		||||
    mod test {
 | 
			
		||||
        use super::*;
 | 
			
		||||
 | 
			
		||||
        #[test]
 | 
			
		||||
        fn button_has_key() {
 | 
			
		||||
            let button = squeek_button_new(0, 0);
 | 
			
		||||
            let state = squeek_button_get_key(button);
 | 
			
		||||
            assert_eq!(squeek_button_has_key(button, state.clone()), 1);
 | 
			
		||||
            let other_button = squeek_button_new(0, 0);
 | 
			
		||||
            assert_eq!(squeek_button_has_key(other_button, state.clone()), 0);
 | 
			
		||||
            let other_state = ::keyboard::c::squeek_key_new(0);
 | 
			
		||||
            assert_eq!(squeek_button_has_key(button, other_state), 0);
 | 
			
		||||
            let shared_button = squeek_button_new_with_state(button);
 | 
			
		||||
            assert_eq!(squeek_button_has_key(shared_button, state), 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug)]
 | 
			
		||||
pub struct Size {
 | 
			
		||||
    pub width: f64,
 | 
			
		||||
    pub height: f64,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// The graphical representation of a button
 | 
			
		||||
#[derive(Clone, Debug)]
 | 
			
		||||
pub struct Button {
 | 
			
		||||
    oref: c::OutlineRef,
 | 
			
		||||
    /// TODO: abolish Option, buttons should be created with bounds fully formed
 | 
			
		||||
    /// Position relative to some origin (i.e. parent/row)
 | 
			
		||||
    bounds: Option<c::Bounds>,
 | 
			
		||||
    /// current state, shared with other buttons
 | 
			
		||||
    pub state: Rc<RefCell<KeyState>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: derive from the style/margin/padding
 | 
			
		||||
const BUTTON_SPACING: f64 = 4.0;
 | 
			
		||||
const ROW_SPACING: f64 = 7.0;
 | 
			
		||||
 | 
			
		||||
/// The graphical representation of a row of buttons
 | 
			
		||||
pub struct Row {
 | 
			
		||||
    buttons: Vec<Box<Button>>,
 | 
			
		||||
    /// Angle is not really used anywhere...
 | 
			
		||||
    angle: i32,
 | 
			
		||||
    /// Position relative to some origin (i.e. parent/view origin)
 | 
			
		||||
    bounds: Option<c::Bounds>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Row {
 | 
			
		||||
    fn new(angle: i32) -> Row {
 | 
			
		||||
        Row {
 | 
			
		||||
            buttons: Vec::new(),
 | 
			
		||||
            angle: angle,
 | 
			
		||||
            bounds: None,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn last(positions: &Vec<c::Bounds>) -> Option<&c::Bounds> {
 | 
			
		||||
        let len = positions.len();
 | 
			
		||||
        match len {
 | 
			
		||||
            0 => None,
 | 
			
		||||
            l => Some(&positions[l - 1])
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn calculate_button_positions(outlines: Vec<c::Bounds>)
 | 
			
		||||
        -> Vec<c::Bounds>
 | 
			
		||||
    {
 | 
			
		||||
        let mut x_offset = 0f64;
 | 
			
		||||
        outlines.iter().map(|outline| {
 | 
			
		||||
            x_offset += outline.x; // account for offset outlines
 | 
			
		||||
            let position = c::Bounds {
 | 
			
		||||
                x: x_offset,
 | 
			
		||||
                ..outline.clone()
 | 
			
		||||
            };
 | 
			
		||||
            x_offset += outline.width + BUTTON_SPACING;
 | 
			
		||||
            position
 | 
			
		||||
        }).collect()
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    fn calculate_row_size(positions: &Vec<c::Bounds>) -> Size {
 | 
			
		||||
        let max_height = positions.iter().map(
 | 
			
		||||
            |bounds| FloatOrd(bounds.height)
 | 
			
		||||
        ).max()
 | 
			
		||||
            .unwrap_or(FloatOrd(0f64))
 | 
			
		||||
            .0;
 | 
			
		||||
        
 | 
			
		||||
        let total_width = match Row::last(positions) {
 | 
			
		||||
            Some(position) => position.x + position.width,
 | 
			
		||||
            None => 0f64,
 | 
			
		||||
        };
 | 
			
		||||
        Size { width: total_width, height: max_height }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Finds the first button that covers the specified point
 | 
			
		||||
    /// relative to row's position's origin
 | 
			
		||||
    fn find_button_by_position(&mut self, point: c::Point)
 | 
			
		||||
        -> Option<&mut Box<Button>>
 | 
			
		||||
    {
 | 
			
		||||
        let row_bounds = self.bounds.as_ref().expect("Missing bounds on row");
 | 
			
		||||
        let origin = c::Point {
 | 
			
		||||
            x: row_bounds.x,
 | 
			
		||||
            y: row_bounds.y,
 | 
			
		||||
        };
 | 
			
		||||
        let angle = self.angle;
 | 
			
		||||
        self.buttons.iter_mut().find(|button| {
 | 
			
		||||
            let bounds = button.bounds
 | 
			
		||||
                .as_ref().expect("Missing bounds on button")
 | 
			
		||||
                .clone();
 | 
			
		||||
            let point = point.clone();
 | 
			
		||||
            let origin = origin.clone();
 | 
			
		||||
            procedures::is_point_inside(bounds, point, origin, angle)
 | 
			
		||||
        })
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct View {
 | 
			
		||||
    /// Position relative to keyboard origin
 | 
			
		||||
    bounds: c::Bounds,
 | 
			
		||||
    rows: Vec<Box<Row>>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl View {
 | 
			
		||||
    /// Determines the positions of rows based on their sizes
 | 
			
		||||
    /// Each row will be centered horizontally
 | 
			
		||||
    /// The collection of rows will not be altered vertically
 | 
			
		||||
    /// (TODO: maybe make view bounds a constraint,
 | 
			
		||||
    /// and derive a scaling factor that lets contents fit into view)
 | 
			
		||||
    /// (or TODO: blow up view bounds to match contents
 | 
			
		||||
    /// and then scale the entire thing)
 | 
			
		||||
    fn calculate_row_positions(&self, sizes: Vec<Size>) -> Vec<c::Bounds> {
 | 
			
		||||
        let mut y_offset = self.bounds.y;
 | 
			
		||||
        sizes.into_iter().map(|size| {
 | 
			
		||||
            let position = c::Bounds {
 | 
			
		||||
                x: (self.bounds.width - size.width) / 2f64,
 | 
			
		||||
                y: y_offset,
 | 
			
		||||
                width: size.width,
 | 
			
		||||
                height: size.height,
 | 
			
		||||
            };
 | 
			
		||||
            y_offset += size.height + ROW_SPACING;
 | 
			
		||||
            position
 | 
			
		||||
        }).collect()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Uses button outline information to place all buttons and rows inside.
 | 
			
		||||
    /// The view itself will not be affected by the sizes
 | 
			
		||||
    fn place_buttons_with_sizes(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        button_outlines: Vec<Vec<c::Bounds>>
 | 
			
		||||
    ) {
 | 
			
		||||
        // Determine all positions
 | 
			
		||||
        let button_positions: Vec<_>
 | 
			
		||||
            = button_outlines.into_iter()
 | 
			
		||||
                .map(Row::calculate_button_positions)
 | 
			
		||||
                .collect();
 | 
			
		||||
        
 | 
			
		||||
        let row_sizes = button_positions.iter()
 | 
			
		||||
            .map(Row::calculate_row_size)
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        let row_positions = self.calculate_row_positions(row_sizes);
 | 
			
		||||
 | 
			
		||||
        // Apply all positions
 | 
			
		||||
        for ((mut row, row_position), button_positions)
 | 
			
		||||
            in self.rows.iter_mut()
 | 
			
		||||
                .zip(row_positions)
 | 
			
		||||
                .zip(button_positions) {
 | 
			
		||||
            row.bounds = Some(row_position);
 | 
			
		||||
            for (mut button, button_position)
 | 
			
		||||
                in row.buttons.iter_mut()
 | 
			
		||||
                    .zip(button_positions) {
 | 
			
		||||
                button.bounds = Some(button_position);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Finds the first button that covers the specified point
 | 
			
		||||
    /// relative to view's position's origin
 | 
			
		||||
    fn find_button_by_position(&mut self, point: c::Point)
 | 
			
		||||
        -> Option<&mut Box<Button>>
 | 
			
		||||
    {
 | 
			
		||||
        // make point relative to the inside of the view,
 | 
			
		||||
        // which is the origin of all rows
 | 
			
		||||
        let point = c::Point {
 | 
			
		||||
            x: point.x - self.bounds.x,
 | 
			
		||||
            y: point.y - self.bounds.y,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        self.rows.iter_mut().find_map(
 | 
			
		||||
            |row| row.find_button_by_position(point.clone())
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mod procedures {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    
 | 
			
		||||
    type Path<'v> = (&'v Box<Row>, &'v Box<Button>);
 | 
			
		||||
 | 
			
		||||
    /// Finds all `(row, button)` paths that refer to the specified key `state`
 | 
			
		||||
    pub fn find_key_paths<'v, 's>(
 | 
			
		||||
        view: &'v View,
 | 
			
		||||
        state: &'s Rc<RefCell<KeyState>>
 | 
			
		||||
    ) -> Vec<Path<'v>> {
 | 
			
		||||
        view.rows.iter().flat_map(|row| {
 | 
			
		||||
            let row_paths: Vec<Path> = row.buttons.iter().filter_map(|button| {
 | 
			
		||||
                if Rc::ptr_eq(&button.state, state) {
 | 
			
		||||
                    Some((row, button))
 | 
			
		||||
                } else {
 | 
			
		||||
                    None
 | 
			
		||||
                }
 | 
			
		||||
            }).collect(); // collecting not to let row references outlive the function
 | 
			
		||||
            row_paths.into_iter()
 | 
			
		||||
        }).collect()
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /// Checks if point is inside bounds which are rotated by angle.
 | 
			
		||||
    /// FIXME: what's origin about?
 | 
			
		||||
    pub fn is_point_inside(
 | 
			
		||||
        bounds: c::Bounds,
 | 
			
		||||
        point: c::Point,
 | 
			
		||||
        origin: c::Point,
 | 
			
		||||
        angle: i32
 | 
			
		||||
    ) -> bool {
 | 
			
		||||
        (unsafe {
 | 
			
		||||
            c::procedures::eek_are_bounds_inside(bounds, point, origin, angle)
 | 
			
		||||
        }) == 1
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -1,9 +1,4 @@
 | 
			
		||||
#[macro_use]
 | 
			
		||||
mod bitflags;
 | 
			
		||||
 | 
			
		||||
mod float_ord;
 | 
			
		||||
mod imservice;
 | 
			
		||||
mod keyboard;
 | 
			
		||||
mod layout;
 | 
			
		||||
mod symbol;
 | 
			
		||||
mod util;
 | 
			
		||||
 | 
			
		||||
@ -16,20 +16,30 @@ sources = [
 | 
			
		||||
  'server-context-service.c',
 | 
			
		||||
  'wayland.c',
 | 
			
		||||
  '../eek/eek.c',
 | 
			
		||||
  '../eek/eek-container.c',
 | 
			
		||||
  '../eek/eek-element.c',
 | 
			
		||||
  '../eek/eek-gtk-keyboard.c',
 | 
			
		||||
  '../eek/eek-key.c',
 | 
			
		||||
  '../eek/eek-keyboard.c',
 | 
			
		||||
  '../eek/eek-keyboard-drawing.c',
 | 
			
		||||
  '../eek/eek-keysym.c',
 | 
			
		||||
  '../eek/eek-layout.c',
 | 
			
		||||
  '../eek/eek-renderer.c',
 | 
			
		||||
  '../eek/eek-section.c',
 | 
			
		||||
  '../eek/eek-serializable.c',
 | 
			
		||||
  '../eek/eek-symbol.c',
 | 
			
		||||
  '../eek/eek-symbol-matrix.c',
 | 
			
		||||
  '../eek/eek-text.c',
 | 
			
		||||
  '../eek/eek-theme.c',
 | 
			
		||||
  '../eek/eek-theme-context.c',
 | 
			
		||||
  '../eek/eek-theme-node.c',
 | 
			
		||||
  '../eek/eek-types.c',
 | 
			
		||||
  '../eek/eek-xml-layout.c',
 | 
			
		||||
  '../eek/layersurface.c',
 | 
			
		||||
  dbus_src,
 | 
			
		||||
  enums,
 | 
			
		||||
  keysym_entries,
 | 
			
		||||
  marshalers,
 | 
			
		||||
  '../eekboard/key-emitter.c',
 | 
			
		||||
  '../eekboard/eekboard-context-service.c',
 | 
			
		||||
  '../eekboard/eekboard-context.c',
 | 
			
		||||
 | 
			
		||||
@ -83,7 +83,9 @@ on_notify_keyboard (GObject              *object,
 | 
			
		||||
                    GParamSpec           *spec,
 | 
			
		||||
                    ServerContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    const LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
    const EekKeyboard *keyboard;
 | 
			
		||||
 | 
			
		||||
    keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
 | 
			
		||||
    if (!keyboard)
 | 
			
		||||
        g_error("Programmer error: keyboard layout was unset!");
 | 
			
		||||
@ -139,12 +141,13 @@ set_geometry (ServerContextService *context)
 | 
			
		||||
    GdkWindow   *root     = gdk_screen_get_root_window (screen);
 | 
			
		||||
    GdkDisplay  *display  = gdk_display_get_default ();
 | 
			
		||||
    GdkMonitor  *monitor  = gdk_display_get_monitor_at_window (display, root);
 | 
			
		||||
    LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
    EekKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
 | 
			
		||||
    GdkRectangle rect;
 | 
			
		||||
    EekBounds bounds;
 | 
			
		||||
 | 
			
		||||
    gdk_monitor_get_geometry (monitor, &rect);
 | 
			
		||||
    EekBounds bounds = squeek_view_get_bounds (level_keyboard_current(keyboard));
 | 
			
		||||
    eek_element_get_bounds (EEK_ELEMENT(keyboard), &bounds);
 | 
			
		||||
 | 
			
		||||
    if (eekboard_context_service_get_fullscreen (EEKBOARD_CONTEXT_SERVICE(context))) {
 | 
			
		||||
        gint width  = rect.width;
 | 
			
		||||
@ -225,15 +228,25 @@ destroy_window (ServerContextService *context)
 | 
			
		||||
static void
 | 
			
		||||
make_widget (ServerContextService *context)
 | 
			
		||||
{
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekTheme *theme;
 | 
			
		||||
 | 
			
		||||
    if (context->widget) {
 | 
			
		||||
        gtk_widget_destroy(context->widget);
 | 
			
		||||
        context->widget = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    LevelKeyboard *keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
    theme = eek_theme_new ("resource:///sm/puri/squeekboard/style.css",
 | 
			
		||||
                           NULL,
 | 
			
		||||
                           NULL);
 | 
			
		||||
 | 
			
		||||
    keyboard = eekboard_context_service_get_keyboard (EEKBOARD_CONTEXT_SERVICE(context));
 | 
			
		||||
 | 
			
		||||
    context->widget = eek_gtk_keyboard_new (keyboard);
 | 
			
		||||
 | 
			
		||||
    eek_gtk_keyboard_set_theme (EEK_GTK_KEYBOARD(context->widget), theme);
 | 
			
		||||
    g_clear_object (&theme);
 | 
			
		||||
 | 
			
		||||
    gtk_widget_set_has_tooltip (context->widget, TRUE);
 | 
			
		||||
    gtk_container_add (GTK_CONTAINER(context->window), context->widget);
 | 
			
		||||
    gtk_widget_show (context->widget);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										24
									
								
								src/symbol.h
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/symbol.h
									
									
									
									
									
								
							@ -1,24 +0,0 @@
 | 
			
		||||
#ifndef __SYMBOL_H
 | 
			
		||||
#define __SYMBOL_H
 | 
			
		||||
 | 
			
		||||
#include "stdbool.h"
 | 
			
		||||
#include "inttypes.h"
 | 
			
		||||
// Defined in Rust
 | 
			
		||||
 | 
			
		||||
struct squeek_symbol;
 | 
			
		||||
struct squeek_symbols;
 | 
			
		||||
 | 
			
		||||
void squeek_symbols_add(struct squeek_symbols*,
 | 
			
		||||
                        const char *element_name,
 | 
			
		||||
                        const char *text, uint32_t keyval,
 | 
			
		||||
                        const char *label, const char *icon,
 | 
			
		||||
                        const char *tooltip);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const char *squeek_symbol_get_name(struct squeek_symbol* symbol);
 | 
			
		||||
const char *squeek_symbol_get_label(struct squeek_symbol* symbol);
 | 
			
		||||
const char *squeek_symbol_get_icon_name(struct squeek_symbol* symbol);
 | 
			
		||||
uint32_t squeek_symbol_get_modifier_mask(struct squeek_symbol* symbol);
 | 
			
		||||
 | 
			
		||||
void squeek_symbol_print(struct squeek_symbol* symbol);
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										138
									
								
								src/symbol.rs
									
									
									
									
									
								
							
							
						
						
									
										138
									
								
								src/symbol.rs
									
									
									
									
									
								
							@ -1,138 +0,0 @@
 | 
			
		||||
use std::ffi::CString;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// Gathers stuff defined in C or called by C
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use super::*;
 | 
			
		||||
    
 | 
			
		||||
    use std::ffi::CStr;
 | 
			
		||||
    use std::os::raw::c_char;
 | 
			
		||||
    use std::ptr;
 | 
			
		||||
    
 | 
			
		||||
    // The following defined in C
 | 
			
		||||
    
 | 
			
		||||
    // Legacy; Will never be used in Rust as a bit field
 | 
			
		||||
    enum ModifierMask {
 | 
			
		||||
        Nothing = 0,
 | 
			
		||||
        Shift = 1,
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // The following defined in Rust.
 | 
			
		||||
    
 | 
			
		||||
    // TODO: wrap naked pointers to Rust data inside RefCells to prevent multiple writers
 | 
			
		||||
    // Symbols are owned by Rust and will move towards no C manipulation, so it may make sense not to wrap them
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_symbol_get_name(symbol: *const Symbol) -> *const c_char {
 | 
			
		||||
        let symbol = unsafe { &*symbol };
 | 
			
		||||
        match &symbol.action {
 | 
			
		||||
            Action::Submit { text: Some(text), .. } => text.as_ptr(),
 | 
			
		||||
            _ => ptr::null(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_symbol_get_label(symbol: *const Symbol) -> *const c_char {
 | 
			
		||||
        let symbol = unsafe { &*symbol };
 | 
			
		||||
        match &symbol.label {
 | 
			
		||||
            Label::Text(text) => text.as_ptr(),
 | 
			
		||||
            // returning static strings to C is a bit cumbersome
 | 
			
		||||
            Label::IconName(_) => unsafe {
 | 
			
		||||
                CStr::from_bytes_with_nul_unchecked(b"icon\0")
 | 
			
		||||
            }.as_ptr(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_symbol_get_icon_name(symbol: *const Symbol) -> *const c_char {
 | 
			
		||||
        let symbol = unsafe { &*symbol };
 | 
			
		||||
        match &symbol.label {
 | 
			
		||||
            Label::Text(_) => ptr::null(),
 | 
			
		||||
            Label::IconName(name) => name.as_ptr(),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Legacy; throw away
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_symbol_get_modifier_mask(symbol: *const Symbol) -> u32 {
 | 
			
		||||
        let symbol = unsafe { &*symbol };
 | 
			
		||||
        (match &symbol.action {
 | 
			
		||||
            Action::SetLevel(1) => ModifierMask::Shift,
 | 
			
		||||
            _ => ModifierMask::Nothing,
 | 
			
		||||
        }) as u32
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[no_mangle]
 | 
			
		||||
    pub extern "C"
 | 
			
		||||
    fn squeek_symbol_print(symbol: *const Symbol) {
 | 
			
		||||
        let symbol = unsafe { &*symbol };
 | 
			
		||||
        println!("{:?}", symbol);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Just defines some int->identifier mappings for convenience
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum KeySym {
 | 
			
		||||
    Unknown = 0,
 | 
			
		||||
    Shift = 0xffe1,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl KeySym {
 | 
			
		||||
    pub fn from_u32(num: u32) -> KeySym {
 | 
			
		||||
        match num {
 | 
			
		||||
            0xffe1 => KeySym::Shift,
 | 
			
		||||
            _ => KeySym::Unknown,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct XKeySym(pub u32);
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum Label {
 | 
			
		||||
    /// Text used to display the symbol
 | 
			
		||||
    Text(CString),
 | 
			
		||||
    /// Icon name used to render the symbol
 | 
			
		||||
    IconName(CString),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Use to switch layouts
 | 
			
		||||
type Level = u8;
 | 
			
		||||
 | 
			
		||||
/// Use to send modified keypresses
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum Modifier {
 | 
			
		||||
    Control,
 | 
			
		||||
    Alt,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Action to perform on the keypress and, in reverse, on keyrelease
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub enum Action {
 | 
			
		||||
    /// Switch to this level TODO: reverse?
 | 
			
		||||
    SetLevel(Level),
 | 
			
		||||
    /// Set this modifier TODO: release?
 | 
			
		||||
    SetModifier(Modifier),
 | 
			
		||||
    /// Submit some text
 | 
			
		||||
    Submit {
 | 
			
		||||
        /// orig: Canonical name of the symbol
 | 
			
		||||
        text: Option<CString>,
 | 
			
		||||
        /// The key events this symbol submits when submitting text is not possible
 | 
			
		||||
        keys: Vec<XKeySym>,
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Contains a static description of a particular key's actions
 | 
			
		||||
#[derive(Debug, Clone)]
 | 
			
		||||
pub struct Symbol {
 | 
			
		||||
    /// The action that this key performs
 | 
			
		||||
    pub action: Action,
 | 
			
		||||
    /// Label to display to the user
 | 
			
		||||
    pub label: Label,
 | 
			
		||||
    // FIXME: is it used?
 | 
			
		||||
    pub tooltip: Option<CString>,
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										50
									
								
								src/util.rs
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/util.rs
									
									
									
									
									
								
							@ -1,50 +0,0 @@
 | 
			
		||||
pub mod c {
 | 
			
		||||
    use std::ffi::{ CStr, CString };
 | 
			
		||||
    use std::os::raw::c_char;
 | 
			
		||||
    use std::str::Utf8Error;
 | 
			
		||||
    
 | 
			
		||||
    #[allow(dead_code)]
 | 
			
		||||
    pub fn as_str(s: &*const c_char) -> Result<Option<&str>, Utf8Error> {
 | 
			
		||||
        if s.is_null() {
 | 
			
		||||
            Ok(None)
 | 
			
		||||
        } else {
 | 
			
		||||
            unsafe {CStr::from_ptr(*s)}
 | 
			
		||||
                .to_str()
 | 
			
		||||
                .map(Some)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    pub fn as_cstr(s: &*const c_char) -> Option<&CStr> {
 | 
			
		||||
        if s.is_null() {
 | 
			
		||||
            None
 | 
			
		||||
        } else {
 | 
			
		||||
            Some(unsafe {CStr::from_ptr(*s)})
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn into_cstring(s: *const c_char) -> Result<Option<CString>, std::ffi::NulError> {
 | 
			
		||||
        if s.is_null() {
 | 
			
		||||
            Ok(None)
 | 
			
		||||
        } else {
 | 
			
		||||
            CString::new(
 | 
			
		||||
                unsafe {CStr::from_ptr(s)}.to_bytes()
 | 
			
		||||
            ).map(Some)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    #[cfg(test)]
 | 
			
		||||
    mod tests {
 | 
			
		||||
        use super::*;
 | 
			
		||||
        use std::ptr;
 | 
			
		||||
        
 | 
			
		||||
        #[test]
 | 
			
		||||
        fn test_null_cstring() {
 | 
			
		||||
            assert_eq!(into_cstring(ptr::null()), Ok(None))
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        #[test]
 | 
			
		||||
        fn test_null_str() {
 | 
			
		||||
            assert_eq!(as_str(&ptr::null()), Ok(None))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -24,22 +24,24 @@
 | 
			
		||||
static void
 | 
			
		||||
test_create (void)
 | 
			
		||||
{
 | 
			
		||||
    EekBounds bounds = {0};
 | 
			
		||||
    struct squeek_view *view = squeek_view_new(bounds);
 | 
			
		||||
    struct squeek_button *button0, *button1;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    EekSection *section;
 | 
			
		||||
    EekKey *key0, *key1;
 | 
			
		||||
 | 
			
		||||
    struct squeek_row *row = squeek_view_create_row (view, 0);
 | 
			
		||||
    g_assert (row);
 | 
			
		||||
    button0 = squeek_row_create_button (row, 1, 0);
 | 
			
		||||
    g_assert (button0);
 | 
			
		||||
    button1 = squeek_row_create_button (row, 2, 0);
 | 
			
		||||
    g_assert (button1);
 | 
			
		||||
    keyboard = g_object_new (EEK_TYPE_KEYBOARD, NULL);
 | 
			
		||||
    section = eek_keyboard_create_section (keyboard);
 | 
			
		||||
    g_assert (EEK_IS_SECTION(section));
 | 
			
		||||
    eek_section_add_row (section, 2, EEK_ORIENTATION_HORIZONTAL);
 | 
			
		||||
    key0 = eek_section_create_key (section, "key0", 1, 0, 0);
 | 
			
		||||
    g_assert (EEK_IS_KEY(key0));
 | 
			
		||||
    key1 = eek_section_create_key (section, "key1", 2, 1, 0);
 | 
			
		||||
    g_assert (EEK_IS_KEY(key1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    g_test_init (&argc, &argv, NULL);
 | 
			
		||||
    gtk_test_init (&argc, &argv, NULL);
 | 
			
		||||
    g_test_add_func ("/eek-simple-test/create", test_create);
 | 
			
		||||
    return g_test_run ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -30,7 +30,7 @@ static void
 | 
			
		||||
test_output_parse (void)
 | 
			
		||||
{
 | 
			
		||||
    EekLayout *layout;
 | 
			
		||||
    LevelKeyboard *keyboard;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
@ -39,15 +39,15 @@ test_output_parse (void)
 | 
			
		||||
 | 
			
		||||
    /* We don't need the context service to parse an XML file, so we can pass
 | 
			
		||||
       NULL when creating a keyboard. */
 | 
			
		||||
    keyboard = eek_xml_layout_real_create_keyboard(layout, NULL);
 | 
			
		||||
    keyboard = eek_keyboard_new (NULL, layout, 640, 480);
 | 
			
		||||
    g_object_unref (layout);
 | 
			
		||||
    level_keyboard_free(keyboard);
 | 
			
		||||
    g_object_unref (keyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    g_test_init (&argc, &argv, NULL);
 | 
			
		||||
    gtk_test_init (&argc, &argv, NULL);
 | 
			
		||||
 | 
			
		||||
    g_test_add_func ("/eek-xml-test/output-parse", test_output_parse);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -32,14 +32,14 @@ static void
 | 
			
		||||
test_check_xkb (void)
 | 
			
		||||
{
 | 
			
		||||
    EekLayout *layout;
 | 
			
		||||
    LevelKeyboard *keyboard;
 | 
			
		||||
    EekKeyboard *keyboard;
 | 
			
		||||
    GError *error;
 | 
			
		||||
 | 
			
		||||
    error = NULL;
 | 
			
		||||
    layout = eek_xml_layout_new ("us", &error);
 | 
			
		||||
    g_assert_no_error (error);
 | 
			
		||||
 | 
			
		||||
    keyboard = eek_xml_layout_real_create_keyboard(layout, NULL);
 | 
			
		||||
    keyboard = eek_keyboard_new (NULL, layout, 640, 480);
 | 
			
		||||
    gchar *keymap_str = eek_keyboard_get_keymap(keyboard);
 | 
			
		||||
 | 
			
		||||
    struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
 | 
			
		||||
@ -58,13 +58,13 @@ test_check_xkb (void)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    g_object_unref (layout);
 | 
			
		||||
    level_keyboard_free(keyboard);
 | 
			
		||||
    g_object_unref (keyboard);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
    g_test_init (&argc, &argv, NULL);
 | 
			
		||||
    gtk_test_init (&argc, &argv, NULL);
 | 
			
		||||
 | 
			
		||||
    g_test_add_func ("/test-keymap-generation/check-xkb", test_check_xkb);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user