summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/luatex/luatexko/luatexko-uhc2utf8.lua
blob: 9d73b622ea02bd676d09b8cb83df37fc52ef2a5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
-- luatexko-uhc2utf8.lua
--
-- Copyright (c) 2013-2017  Dohyun Kim  <nomos at ktug org>
--                          Soojin Nam  <jsunam at gmail com>
--
-- This work may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either version 1.3c
-- of this license or (at your option) any later version.
-- The latest version of this license is in
--   http://www.latex-project.org/lppl.txt
-- and version 1.3c or later is part of all distributions of LaTeX
-- version 2006/05/20 or later.

luatexbase.provides_module({
  name        = "luatexko-uhc2utf8",
  version     = "1.16",
  date        = "2017/02/06",
  author      = "Dohyun Kim, Soojin Nam",
  description = "UHC (CP949) input encoding",
  license     = "LPPL v1.3+",
})

luatexkouhc2utf8 = luatexkouhc2utf8 or {}
local luatexkouhc2utf8 = luatexkouhc2utf8

local format = string.format
require "unicode"
local unicodeutf8 = unicode.utf8
local ugsub = unicodeutf8.gsub
local ubyte = unicodeutf8.byte
local uchar = unicodeutf8.char
local floor = math.floor
local kpse_find_file = kpse.find_file
local add_to_callback = luatexbase.add_to_callback
local remove_from_callback = luatexbase.remove_from_callback

local function get_uhc_uni_table()
  local t_uhc2ucs = {}
  local file = kpse_find_file("KSCms-UHC-UCS2","cmap files")
  if file then
    file = io.open(file, "r")
    while true do
      local line = file:read("*line")
      if not line then break end
      local ea,eb,uni = line:match("<(%x+)>%s+<(%x+)>%s+<(%x+)>")
      if ea and eb and uni then
        ea, eb, uni = tonumber(ea,16),tonumber(eb,16),tonumber(uni,16)
        for i=ea,eb do
          t_uhc2ucs[i] = uni
          uni = uni + 1
        end
      end
    end
    file:close()
  end
  return t_uhc2ucs
end

local t_uhc2ucs = t_uhc2ucs or get_uhc_uni_table()

local function not_utf8lowbyte(t)
  for _,v in ipairs(t) do
    -- rough checking
    if v < 0x80 or v > 0xBF then return true end
  end
  return false
end

local uhc_to_utf8 = function(buffer)
  if not buffer then return end
  -- check if buffer is already utf-8; better solution?
  local i, buflen = 1, buffer:len()+1
  while i < buflen do
    local a = buffer:byte(i)
    if a < 0x80 then
      i = i + 1
    elseif a < 0xC2 then
      break
    elseif a < 0xE0 then
      if not_utf8lowbyte({buffer:byte(i+1)}) then break end
      i = i + 2
    elseif a < 0xF0 then
      if not_utf8lowbyte({buffer:byte(i+1,i+2)}) then break end
      i = i + 3
    elseif a < 0xF5 then
      if not_utf8lowbyte({buffer:byte(i+1,i+3)}) then break end
      i = i + 4
    else
      break
    end
  end
  if i == buflen then return nil end
  -- now convert to utf8
  buffer = buffer:gsub("([\129-\253])([\65-\254])",
  function(a, b)
    local utf = t_uhc2ucs[a:byte() * 256 + b:byte()]
    if utf then return uchar(utf) end
  end)
  return buffer
end

local function startconvert ()
  add_to_callback('process_input_buffer', uhc_to_utf8, 'luatexko-uhctoutf8', 1)
end
luatexkouhc2utf8.startconvert = startconvert

local function stopconvert ()
  remove_from_callback('process_input_buffer', 'luatexko-uhctoutf8')
end
luatexkouhc2utf8.stopconvert = stopconvert

-----------------------------------------
-- Hangul Windows OS uses CP949 filenames
-----------------------------------------
local function get_uni_uhc_table()
  local t_ucs2uhc = {}
  for i,v in pairs(t_uhc2ucs) do
    t_ucs2uhc[v] = i
  end
  return t_ucs2uhc
end

local t_ucs2uhc = t_ucs2uhc or get_uni_uhc_table()

local function utf8_to_uhc (name)
  if not name then return end
  name = ugsub(name, "[\161-\239\191\166]", -- 00A1..FFE6
  function(u)
    local c = t_ucs2uhc[ubyte(u)]
    if c then
      return format("%c%c", floor(c/256), c%256)
    end
  end)
  return name
end

local function uhc_find_file (file, ...)
  local f = kpse_find_file(file, ...)
  if f then return f end
  f = utf8_to_uhc(file)
  return f and kpse_find_file(f, ...)
end

local function start_uhc_filename ()
  add_to_callback('find_read_file', function(id, name) return uhc_find_file(name) end, 'luatexko-touhc-findreadfile')
  add_to_callback('find_image_file', uhc_find_file, 'luatexko-touhc-findimagefile')
  kpse.find_file = uhc_find_file
end
luatexkouhc2utf8.start_uhc_filename = start_uhc_filename

local function stop_uhc_filename ()
  remove_from_callback('find_read_file', 'luatexko-touhc-findreadfile')
  remove_from_callback('find_image_file', 'luatexko-touhc-findimagefile')
  kpse.find_file = kpse_find_file
end
luatexkouhc2utf8.stop_uhc_filename = stop_uhc_filename