ตอนนี้ก็เริ่มมาหาว่า จะทำยังไงให้ map ระหว่าง keyboard layout ภาษาไทยไปอังกฤษได้ (หรือจากอังกฤษมาไทยได้)
วิธีที่basicสุดๆเลยก็คือ นั่งกด ทีละตัวๆ ระหว่างไทยและอังกฤษ เพื่อทำเป็นตารางขึ้นมา
อืม... ก็ไม่ได้ผิดอะไรนะวิธีนี้ แต่ดูมันถึกเกินไปหน่อย เพราะนอกจากจะต้องไล่กดทีละปุ่มบนkeyboardแล้ว ยังต้องมาไล่อีกรอบนึง เพราะว่าตัวหนังสือก็มีแบบกดshiftค้างไว้ด้วย เหนื่อยแน่ แล้วก็ดูไม่ค่อยมาตรฐานเท่าไหร่เพราะอาจจะมีkeyอะไรลืมกดก็ได้
ก็เลยคิดอีกวิธีขึ้นมา ว่ามันน่าจะมีระบบ keyboard layout อยู่แล้วนะ
ยิ่งใน Linux ทุกอย่างแทบจะเป็นtext file หมด น่าจะเอามาทำอะไรได้
พอค้นไปค้นมา ก็ไปเจอไฟล์หลักๆ มาสามไฟล์
http://cvsweb.xfree86.org/cvsweb/*checkout*/xc/programs/xkbcomp/symbols/th?rev=HEAD&content-type=text/plain
http://cvsweb.xfree86.org/cvsweb/*checkout*/xc/programs/xkbcomp/symbols/us?rev=HEAD&content-type=text/plain
http://cvsweb.xfree86.org/cvsweb/*checkout*/xc/include/keysymdef.h?rev=1.1.1.4
สามไฟล์นี้คือ th layout, en-us layout, symbol โดยทั้งหมดมาจากpackageที่ชื่อ xc ของ XFree86 ทั้งหมด
คราวนี้ก็เริ่มง่ายละ เพราะว่าข้อมูลต่างๆ ก็พร้อมละ
th layout นี่ก็คือปุ่มกดทุกปุ่มบน keyboard ในภาษาไทย
en-us layout ก็คือปุ่มกดทุกปุ่มบน keyboard ภาษาอังกฤษ
ส่วน keysymdef นี่คือการแปลงจากค่าสัญลักษณ์ของปุ่มกดนั้น ให้กลายเป็นตัวอักษร อย่างเช่น XK_Thai_kokai---> 0xda1 (จาก ก.ไก่ --> 0xda1)
คราวนี้ก็จะเห็นว่าข้อมูลในไฟล์มันรกมาก ในสองไฟล์แรก
ก็เลยจัดการทำความสะอาดซักหน่อย (ด้วย find&replace)
เลยได้เป็นไฟล์ประมาณนี้
จะเห็นว่าเป็น 3 columns โดยมีความหมายดังนี้
อันแรก : keyboard code (keycode) คือรหัสสัญญาณที่keyboardส่งไปให้คอมพิวเตอร์รับรู้ว่าเรากดปุ่มอะไร
อันสอง : ตัวอักษร แบบไม่ได้กดshift
อันที่สาม: ตัวอักษร แบบกดshiftควบคู่ไปด้วย
เช่น บรรทัดที่สาม AE02 slash Thai_leknung หมายความว่า
ถ้ากดปุ่ม AE02 แล้ว กดเฉยๆเลยจะได้เป็น slash (/)
แต่ถ้ากดปุ่ม shift ค้างไว้แล้วกดปุ่ม AE02 จะได้ออกมาเป็น Thai_leknung (๑)
งานที่เหลือก็คือ อย่างแรก map keycode นี้เข้าด้วยกัน ระหว่าง ภาษาไทยและภาษาอังกฤษ
อย่างที่สองก็คือ ต้องแปลง symbol ทั้งหลายนี้ ให้มันกลายเป็นตัวอักษรปกติ ด้วย
อ้อ ตัวอักษรอย่าง 0xda1 ที่ว่าเป็นก.ไก่เนี่ย ความจริงต้องตัด d ออกก่อน เหลือจริงๆแค่ 0xa1 ถึงจะเป็น ก.ไก่ จริงๆ ในระบบ tis-620 นั่นก็ต้องเปลี่ยนให้เป็น utf-8 เอาไว้ใช้งานอย่างอื่นอีก
ซึ่ง... ถ้าจะทำแบบธรรมดาก็จะเหนื่อยไปอีกแล้ว เห็นแล้วมันก็เยอะ เขียนโปรแกรมดีกว่า
แล้วไหนๆ ก็กำลังอยากเรียน Ruby อยู่แล้วด้วย ก็เขียนซะเลย
#!/usr/bin/ruby require 'iconv' require 'optparse' #read keyboard-char map def readFile(filename) mappingtable={} f = File.open(filename, "r") f.each_line do |line| a=line.split mappingtable[a[0]] = [ a[1],a[2] ] end return mappingtable end #read symbol char-keycode map def readKeyTranslate(filename) mappingtable={} f = File.open(filename, "r") f.each_line do |line| if(line=~/^[#]define/) a=line.split mappingtable.store(a[1],a[2]) end end return mappingtable end #convert from hex to tis620 then to utf8 def convHexToChar(hexchar) return nil if hexchar.nil? hexchar.gsub!(/0x./,'') char=hexchar.to_i(16).chr char = Iconv.conv("UTF8","TIS620", char) return char end #dealing with program's arguments $verbose, $thfile, $usfile, $keysymfile = false, 'th.txt', 'us.txt', 'keysymdef.h.txt' options = {} OptionParser.new do |opts| opts.banner="Usage: switchlayout.rb [options]" opts.on("-v", "--verbose", "Run verbosely") {|v| $verbose=options[:verbose]=v} opts.on("-u","--usfile [US_KB_FILE]",String,"Specify en-us keyboard file (default=us.txt)") {|us| $usfile=options[:us]=us} opts.on("-t","--thfile [THAI_KB_FILE]",String,"Specify Thai keyboard file (default=th.txt)") {|th| $thfile=options[:th] = th} opts.on("-k","--keysym [keysymdef.h_FILE]",String,"Specify keyboard symbol file (default=keysymdef.h.txt)") {|keysym| $keysymfile=options[:keysym]=keysym} opts.on_tail("-h","--help","Show this message") { puts opts ; exit} end.parse! puts "Starting process..." #reading all neccessary files thMap = readFile($thfile) puts "Total #{thMap.size} symbols loaded for Thai Mapping" if $verbose usMap = readFile($usfile) puts "Total #{usMap.size} symbols loaded for English(us) Mapping" if $verbose keyCodeMap = readKeyTranslate($keysymfile) puts "Total #{keyCodeMap.size} symbols loaded for KeyCode Mapping" if $verbose #translate from thMap's key symbol to keycode #note: pair[0]=keycode , pair[1]=[char w/o shift, char w/ shift] thMap.each do |pair| print "#{pair[1]} ----> " if $verbose k = pair[1]; k[0] = convHexToChar(keyCodeMap["XK_#{k[0]}"]) k[1] = convHexToChar(keyCodeMap["XK_#{k[1]}"]) puts "#{pair[1]}" if $verbose end #translate from usMap's key symbol to keycode #note: pair[0]=keycode , pair[1]=[char w/o shift, char w/ shift] usMap.each do |pair| print "#{pair[1]} ----> " if $verbose k = pair[1]; k[0] = convHexToChar(keyCodeMap["XK_#{k[0]}"]) k[1] = convHexToChar(keyCodeMap["XK_#{k[1]}"]) puts "#{pair[1]}" if $verbose end #now mapping from enMap & thMap $usTothMap = {} usMap.merge(thMap) do |key, usChar, thChar| $usTothMap.store(usChar[0],thChar[0]) $usTothMap.store(usChar[1],thChar[1]) end $usTothMap.each {|us,th| puts "#{us} ---> #{th}"} if $verbose puts "Total characters mapped = "+$usTothMap.size.to_s #write to file puts "Writing to file ustothmap.txt" f = File.open('ustothmap.txt', 'w') $usTothMap.each {|us,th| f.puts "#{us}\t#{th}"} f.closeอ่านยากแฮะ แบบไม่มีสีเนี่ย
เสียเวลานั่งงมอยู่นานเหมือนกัน กว่าจะรู้ว่าอะไรเป็นอะไรใน Ruby
และแล้ว ในที่สุด ก็ได้ออกมาเป็นไฟล์ usTothMap.txt
คราวนี้ก็จะได้ map ระหว่าง en-us กับ th ได้แล้ว
ทั้งหมดมีแค่ 94 ตัวอักษรเองแฮะ
บางทีเสียเวลานั่งพิมพ์เองจะง่ายกว่ามั๊ง 55555
No comments:
Post a Comment