% file: hnja2hngl.sty
% 
% Copyright (c) 2015-2023 Nova de Hi
% MIT license
%
\ProvidesExplPackage{hnja2hngl}
	{2023/02/27}
	{v1.3}
	{reading hanja for xelatex}

\RequirePackage{l3keys2e}
\RequirePackage{iftex}

\keys_define:nn { hnjahnglpkg }
{
	grruby .bool_set:N = \opt_grruby_bool
}

\keys_set:nn { hnjahnglpkg }
{
	grruby = true
}

\ProcessKeysOptions { hnjahnglpkg }

\bool_if:NTF \opt_grruby_bool
{
	\RequirePackage{grruby}
	\let\hnjahnglgrfoo\grfoo
}
{
	\def\hnjahnglgrfoo #1(#2){
		\ruby{#2}{#1}
	}
}

\tl_new:N \l_code_tl
\tl_new:N \l_hanjacode_tl
\tl_new:N \l_hanglcode_tl
\int_new:N \l_hanjacode_int
\int_new:N \l_hanglcode_int
\clist_new:N \g_hanjastr_clist
\clist_new:N \g_hanglstr_clist
\tl_new:N \g_righttk_tl
\int_new:N \g_lefttk_int

\prop_new:N \g_assignedreading_prop
\tl_new:N \l_readingassigned_tl

\prop_new:N \l_usedhanja_prop

\seq_new:N \l_read_seq
\int_new:N \l_readidx_int

%\bool_new:N \g_dispallhangul_bool

%%% \readhanja 한 글자만 변환하고 한글만을 표시한다.
\NewDocumentCommand \readhanja { m O{} }
{
	\clist_gclear:N \g_hanjastr_clist
	\clist_gclear:N \g_hanglstr_clist
	
	\readhanja_fn { #1 } [ #2 ]

	\group_begin:
	\cs_set_eq:NN \disp_result:NN \disp_onlyhangul:NN
	\disp_result:NN \g_hanjastr_clist \g_hanglstr_clist
	\group_end:
}

\NewDocumentCommand \readhanja_fn { m o }
{
	\regex_match:nnTF { \D } { #2 }
	{
		\tl_gset:Nn \l_readtxt_tl { #2 }
	}
	{
    	\tl_if_empty:nTF { #2 }
    	{
    		\int_set:Nn \l_readidx_int { 0 }
    	}
    	{
    		\int_set:Nn \l_readidx_int { #2 }
    	}
		\tl_gset:Nn \l_readtxt_tl {}
	}
	
	\check_reading_assigned:n { #1 }
	\bool_if:NTF \l_assigned_bool
	{
		\clist_gput_right:Nn \g_hanjastr_clist { #1 }
		\clist_gput_right:Nx \g_hanglstr_clist { \l_readingassigned_tl }
	}
	{
		\_read_hanja_a_char:n { #1 }
	}
}

\cs_new:Npn \_read_hanja_a_char:n #1
{
	\__get_codepoint_fn:nN { #1 } \l_code_tl
	
	\__get_hnglcode_from_file:nnN { \l_code_tl } { hanja2hangul.dat } \l_read_seq

	\tl_set_eq:NN \l_hanjacode_tl \l_code_tl
	
	\tl_if_empty:NTF \l_readtxt_tl 
	{
    	\int_compare:nTF { \l_readidx_int >= \seq_count:N \l_read_seq }
    	{
    		\int_set:Nn \l_readidx_int { \seq_count:N \l_read_seq }
    	}
    	{
    		\int_incr:N \l_readidx_int
    	}
    	
%		\bool_if:NTF \g_dispallhangul_bool
%		{
%			\tl_clear:N \l_hanglcode_tl
%			\seq_indexed_map_inline:Nn \l_read_seq
%			{
%				\int_compare:nTF { ##1 == \l_readidx_int }
%				{
%					\tl_put_right:Nx \l_hanglcode_tl { 65339,##2,65341, }
%				}
%				{
%					\tl_put_right:Nn \l_hanglcode_tl { ##2, }
%				}
%			}
%		}
%		{
	    	\tl_set:Nx \l_hanglcode_tl { \seq_item:Nn \l_read_seq { \int_use:N \l_readidx_int } }
%		}
	}
	{
		\str_if_eq:eeTF { \l_readtxt_tl } { * }
		{
	    	\tl_set:Nx \l_hanglcode_tl { \seq_item:Nn \l_read_seq { 1 } }
			\exp_args:No \proc_head_rule:n { \l_hanglcode_tl }
			\tl_set_eq:NN \l_hanglcode_tl \l_tmpc_tl
		}
		{
			\tl_set:NV \l_hanglcode_tl \l_readtxt_tl
		}
	}

	\clist_gput_right:Nx \g_hanjastr_clist { \l_hanjacode_tl }	
	\bool_if:NTF \g_headrule_bool
	{
		\exp_args:No \proc_head_rule:n { \l_hanglcode_tl }
		\clist_gput_right:Nx \g_hanglstr_clist { \l_tmpc_tl }
	}
	{
		\clist_gput_right:Nx \g_hanglstr_clist { \l_hanglcode_tl }
	}
}

\cs_new:Npn \__get_hnglcode_from_file:nnN #1 #2 #3
{
	\prop_get:NVNTF \l_usedhanja_prop \l_code_tl \l_tmpa_tl
	{
		\seq_gclear:N #3
		\clist_set:Nx \l_tmpb_clist { \l_tmpa_tl }
		\clist_map_inline:Nn \l_tmpb_clist
		{
			\seq_gput_right:Nn #3 { ##1 }
		}
	}
	{
		\__get_hnglcode_from_file_file:nnN { #1 } { #2 } #3
	}
}

\cs_new:Npn \__get_hnglcode_from_file_file:nnN #1 #2 #3
{
	\ior_open:Nn \g_tmpa_ior { #2 }
	
	\ior_map_inline:Nn \g_tmpa_ior
	{
		\parse_one_line:w ##1 \q_stop

		\int_compare:nT { \g_lefttk_int == #1 }
		{
			\seq_gclear:N #3
			\clist_set:Nx \l_tmpb_clist { \g_righttk_tl }
			\clist_map_inline:Nn \l_tmpb_clist
			{
				\seq_gput_right:Nn #3 { ####1 }
			}
			
			\prop_put:NVV \l_usedhanja_prop #1 \g_righttk_tl
			
			\ior_map_break:
		}
	}
	
	\seq_if_empty:NT #3
	{
		\seq_put_right:Nn #3 { ERROR }
	}
	
	\ior_close:N \g_tmpa_ior
}

\cs_new:Npn \parse_one_line:w #1=#2 \q_stop
{
	\int_gset:Nn \g_lefttk_int { #1 }
	\tl_gset:Nn \g_righttk_tl { #2 }
}

\cs_new:Npn \__get_codepoint_fn:nN #1 #2
{
	\str_set_convert:Nnnn \l_tmpa_tl { #1 } {} { clist }
	\tl_gset_eq:NN #2 \l_tmpa_tl
}

\cs_new:Npn \disp_onlyhangul:NN #1 #2
{	
	\clist_map_inline:Nn #2
	{
		\regex_match:nnTF { \d\d\d\d\d } { ##1 }
		{
			\symbol { ##1 }
		}
		{
			##1
		}
	}
}

\cs_new:Npn \proc_head_rule:n #1
{
	\str_case:nnF { #1 }
	{
		{ 45265 } { \tl_set:Nn \l_tmpc_tl { 약 } }
		{ 45285 } { \tl_set:Nn \l_tmpc_tl { 약 } }
		{ 45376 } { \tl_set:Nn \l_tmpc_tl { 여 } }
		{ 45377 } { \tl_set:Nn \l_tmpc_tl { 역 } }
		{ 45380 } { \tl_set:Nn \l_tmpc_tl { 연 } }
		{ 45384 } { \tl_set:Nn \l_tmpc_tl { 열 } }
		{ 45392 } { \tl_set:Nn \l_tmpc_tl { 염 } }
		{ 45393 } { \tl_set:Nn \l_tmpc_tl { 엽 } }
		{ 45397 } { \tl_set:Nn \l_tmpc_tl { 영 } }
		{ 45404 } { \tl_set:Nn \l_tmpc_tl { 예 } }
		{ 45544 } { \tl_set:Nn \l_tmpc_tl { 요 } }
		{ 45545 } { \tl_set:Nn \l_tmpc_tl { 욕 } }
		{ 45684 } { \tl_set:Nn \l_tmpc_tl { 유 } }
		{ 45685 } { \tl_set:Nn \l_tmpc_tl { 육 } }
		{ 46972 } { \tl_set:Nn \l_tmpc_tl { 나 } }
		{ 46973 } { \tl_set:Nn \l_tmpc_tl { 낙 } }
		{ 46976 } { \tl_set:Nn \l_tmpc_tl { 난 } }
		{ 46980 } { \tl_set:Nn \l_tmpc_tl { 날 } }
		{ 46988 } { \tl_set:Nn \l_tmpc_tl { 남 } }
		{ 46989 } { \tl_set:Nn \l_tmpc_tl { 납 } }
		{ 46993 } { \tl_set:Nn \l_tmpc_tl { 낭 } }
		{ 47000 } { \tl_set:Nn \l_tmpc_tl { 내 } }
		{ 47021 } { \tl_set:Nn \l_tmpc_tl { 냉 } }
		{ 47028 } { \tl_set:Nn \l_tmpc_tl { 야 } }
		{ 47049 } { \tl_set:Nn \l_tmpc_tl { 양 } }
		{ 47140 } { \tl_set:Nn \l_tmpc_tl { 여 } }
		{ 47141 } { \tl_set:Nn \l_tmpc_tl { 역 } }
		{ 47144 } { \tl_set:Nn \l_tmpc_tl { 연 } }
		{ 47148 } { \tl_set:Nn \l_tmpc_tl { 열 } }
		{ 47156 } { \tl_set:Nn \l_tmpc_tl { 염 } }
		{ 47157 } { \tl_set:Nn \l_tmpc_tl { 엽 } }
		{ 47161 } { \tl_set:Nn \l_tmpc_tl { 영 } }
		{ 47168 } { \tl_set:Nn \l_tmpc_tl { 예 } }
		{ 47196 } { \tl_set:Nn \l_tmpc_tl { 노 } }
		{ 47197 } { \tl_set:Nn \l_tmpc_tl { 녹 } }
		{ 47200 } { \tl_set:Nn \l_tmpc_tl { 논 } }
		{ 47204 } { \tl_set:Nn \l_tmpc_tl { 놀 } }
		{ 47217 } { \tl_set:Nn \l_tmpc_tl { 농 } }
		{ 47280 } { \tl_set:Nn \l_tmpc_tl { 뇌 } }
		{ 47308 } { \tl_set:Nn \l_tmpc_tl { 요 } }
		{ 47329 } { \tl_set:Nn \l_tmpc_tl { 용 } }
		{ 47336 } { \tl_set:Nn \l_tmpc_tl { 누 } }
		{ 47448 } { \tl_set:Nn \l_tmpc_tl { 유 } }
		{ 47449 } { \tl_set:Nn \l_tmpc_tl { 육 } }
		{ 47452 } { \tl_set:Nn \l_tmpc_tl { 윤 } }
		{ 47456 } { \tl_set:Nn \l_tmpc_tl { 율 } }
		{ 47469 } { \tl_set:Nn \l_tmpc_tl { 융 } }
		{ 47477 } { \tl_set:Nn \l_tmpc_tl { 늑 } }
		{ 47492 } { \tl_set:Nn \l_tmpc_tl { 늠 } }
		{ 47497 } { \tl_set:Nn \l_tmpc_tl { 능 } }
		{ 47532 } { \tl_set:Nn \l_tmpc_tl { 이 } }
		{ 47536 } { \tl_set:Nn \l_tmpc_tl { 인 } }
		{ 47548 } { \tl_set:Nn \l_tmpc_tl { 임 } }
		{ 47549 } { \tl_set:Nn \l_tmpc_tl { 입 } }
	}
	{
		\tl_set:Nn \l_tmpc_tl { #1 }
	}
}

%%% readhanjaword
\NewDocumentCommand \readhanjaword { m }
{
	\seq_set_split:Nnn \l_tmpa_seq { | } { #1 }
	\seq_map_inline:Nn \l_tmpa_seq
	{
		\readhanjaword_sub { ##1 }
	}
}

\NewDocumentCommand \readhanjaword_sub { m }
{
	\readhanja_word_fn { #1 }

	\group_begin:
%	\proc_head_rule:N \g_hanglstr_clist
	\cs_set_eq:NN \disp_result:NN \disp_onlyhangul:NN
	\disp_result:NN \g_hanjastr_clist \g_hanglstr_clist
	\group_end:
	
}

\bool_new:N \g_headrule_bool

\NewDocumentCommand \readhanja_word_fn { m }
{

	\tl_set:Nn \l_tmpa_tl { #1 }

%%% exceptions
	\regex_replace_all:nnN { 不實 } { 不[0]實 } \l_tmpa_tl
	\regex_replace_once:nnN { ^率([^\[\]]) } { 率[1]\1 } \l_tmpa_tl

	\regex_replace_all:nnN { (.) } { \1, } \l_tmpa_tl
	\regex_replace_all:nnN { \,\[\, } { \[ } \l_tmpa_tl
	\regex_replace_all:nnN { \,\] } { \] } \l_tmpa_tl
 	
	\clist_gclear:N \g_hanjastr_clist
	\clist_gclear:N \g_hanglstr_clist
	
	\exp_args:NNx \seq_set_from_clist:Nn \l_tmpa_seq { \tl_use:N \l_tmpa_tl }
	
	\seq_indexed_map_inline:Nn \l_tmpa_seq
	{
		\str_if_eq:nnTF { ##2 } { 不 }
		{
			\clist_gput_right:Nn \g_hanjastr_clist { 不 }
			\clist_gput_right:Nn \g_hanglstr_clist { fffuuu }
		}
		{
    		\str_if_in:nnTF { ##2 } { [ }
    		{
    			\readhanja_fn  ##2 
    		}
    		{
				\bool_if:nTF
				{
				 	\int_compare_p:n { ##1 == 1 } &&
				 	\int_compare_p:n { \tl_count:n { #1 } > 1 }
				}
				{
					\bool_gset_true:N \g_headrule_bool
					\readhanja_fn { ##2 } [ 0 ]
				}
				{
					\bool_gset_false:N \g_headrule_bool
	    			\readhanja_fn { ##2 } [ 0 ]
				}
    		}
		}
	}
	
	\clist_if_in:NnT \g_hanglstr_clist { fffuuu }
	{
    	\tl_clear:N \l_tmpb_tl
    	\clist_map_inline:Nn \g_hanglstr_clist
    	{
    		\str_if_eq:nnTF { ##1 } { fffuuu }
    		{
    			\tl_put_right:Nx \l_tmpb_tl { ##1, }
    		}
    		{
				\regex_match:nnTF { \d\d\d\d\d } { ##1 }
				{
	    			\tl_put_right:Nx \l_tmpb_tl { \symbol{##1}, }
				}
				{
					\tl_put_right:Nn \l_tmpb_tl { ##1, }
				}
    		}
    	}
    	
    	\regex_replace_all:nnN { fffuuu,(.[다-딯따-띻자-짛짜-찧]) } { 48512,\1 } \l_tmpb_tl
    	\regex_replace_all:nnN { fffuuu, } { 48520, } \l_tmpb_tl
	
    	\clist_gset:Nx \g_hanglstr_clist { \l_tmpb_tl }
    	\clist_remove_all:Nn \g_hanglstr_clist {}
	}
}

%%% rwhanja
\NewDocumentCommand \rwhanja { m }
{
%	\readhanja_word_fn { #1 }
	\seq_set_split:Nnn \l_tmpa_seq {|} { #1 }
	
	\clist_gclear:N \g_tmpa_clist
	\clist_gclear:N \g_tmpb_clist
	\seq_map_inline:Nn \l_tmpa_seq
	{
		\readhanja_word_fn { ##1 }
		\clist_gconcat:NNN \g_tmpa_clist \g_tmpa_clist \g_hanjastr_clist 
		\clist_gconcat:NNN \g_tmpb_clist \g_tmpb_clist \g_hanglstr_clist 
	}
	
	\clist_gset_eq:NN \g_hanjastr_clist \g_tmpa_clist
	\clist_gset_eq:NN \g_hanglstr_clist \g_tmpb_clist

	\group_begin:	
	\cs_set_eq:NN \disp_result:NN \disp_rwdisp:NN
	\disp_result:NN \g_hanjastr_clist \g_hanglstr_clist
	\group_end:
}

\NewDocumentCommand \rwhanjachar { m }
{
%	\readhanja_word_fn { #1 }
	\seq_set_split:Nnn \l_tmpa_seq {|} { #1 }
	
	\clist_gclear:N \g_tmpa_clist
	\clist_gclear:N \g_tmpb_clist
	\seq_map_inline:Nn \l_tmpa_seq
	{
		\readhanja_word_fn { ##1 }
		\clist_gconcat:NNN \g_tmpa_clist \g_tmpa_clist \g_hanjastr_clist 
		\clist_gconcat:NNN \g_tmpb_clist \g_tmpb_clist \g_hanglstr_clist 
	}
	
	\clist_gset_eq:NN \g_hanjastr_clist \g_tmpa_clist
	\clist_gset_eq:NN \g_hanglstr_clist \g_tmpb_clist

	\group_begin:	
	\cs_set_eq:NN \disp_result:NN \disp_XXdisp:NN
	\disp_result:NN \g_hanjastr_clist \g_hanglstr_clist
	\group_end:
}


\cs_new:Npn \disp_rwdisp:NN #1 #2
{
	\clist_map_inline:Nn #2
	{
		\regex_match:nnTF { \d\d\d\d\d } { ##1 }
		{
			\symbol { ##1 }
		}
		{
			##1
		}
	}
	(
    	\clist_map_inline:Nn #1
    	{
    		\regex_match:nnTF { \d\d\d\d\d } { ##1 }
    		{
    			\symbol { ##1 }
    		}
    		{
    			##1
    		}
    	}
	)	
}


\cs_new:Npn \disp_XXdisp:NN #1 #2
{
	\int_compare:nTF { \clist_count:N \g_hanjastr_clist == \clist_count:N \g_hanglstr_clist }
	{
		\int_step_inline:nn { \clist_count:N \g_hanjastr_clist }
		{
			\clist_pop:NN \g_hanjastr_clist \l_tmpa_tl
			\clist_pop:NN \g_hanglstr_clist \l_tmpb_tl
			
			\exp_args:Nno \regex_match:nnTF { \d\d\d\d\d } { \l_tmpa_tl }
			{
				\tl_set:Nn \l_tmpc_tl { \symbol { \l_tmpa_tl } }
			}
			{
				\tl_set:NV \l_tmpc_tl \l_tmpa_tl
			}
			
			\exp_args:Nno \regex_match:nnTF { \d\d\d\d\d } { \l_tmpb_tl }
			{
				\tl_set:Nn \l_tmpd_tl { \symbol { \l_tmpb_tl } }
			}
			{
				\tl_set:NV \l_tmpd_tl \l_tmpb_tl
			}
			
			\hnjahnglgrfoo \l_tmpd_tl ( \l_tmpc_tl )	
		}
	}
	{
		\tl_set:Nx \l_tmpa_tl { \clist_use:Nn \g_hanjastr_clist {} }
		\tl_set:Nx \l_tmpb_tl { \clist_use:Nn \g_hanglstr_clist {} }
		
		\hnjahnglgrfoo \l_tmpa_tl ( \l_tmpb_tl )
	}
}


%%% grrwhanja
\NewDocumentCommand \grrwhanja { m }
{
	\readhanja_word_fn { #1 }

	\group_begin:	
	\cs_set_eq:NN \disp_result:NN \disp_grrwdisp:NN
	\disp_result:NN \g_hanjastr_clist \g_hanglstr_clist
	\group_end:
}

\cs_new:Npn \disp_grrwdisp:NN #1 #2
{
	\hnjahnglgrfoo
	\clist_map_inline:Nn #1
	{
		\regex_match:nnTF { \d\d\d\d\d } { ##1 }
		{
			\symbol { ##1 }
		}
		{
			##1
		}
	}
	(
    	\clist_map_inline:Nn #2
    	{
    		\regex_match:nnTF { \d\d\d\d\d } { ##1 }
    		{
    			\symbol { ##1 }
    		}
    		{
    			##1
    		}
    	}
	)	
}

%%%% AssignReading
\NewDocumentCommand \AssignReading { m m }
{
	\prop_put:Nnn \g_assignedreading_prop { #1 } { #2 }
}

\cs_new:Npn \check_reading_assigned:n #1
{
	\prop_get:NnNTF \g_assignedreading_prop { #1 } \l_readingassigned_tl
		{ \bool_set_true:N \l_assigned_bool } { \bool_set_false:N \l_assigned_bool }
}

\NewDocumentCommand \rpSetReading { m }
{
	\clist_set:Nn \l_tmpb_clist { #1 }
	\clist_map_inline:Nn \l_tmpb_clist
	{
		\split_rpsetreading:w ##1 \q_stop
		\prop_put:NVV \g_assignedreading_prop \g_tmpa_tl \g_tmpb_tl
	}
}

\cs_new:Npn \split_rpsetreading:w #1=#2\q_stop
{
	\tl_gset:Nn \g_tmpa_tl { #1 }
	\tl_gset:Nn \g_tmpb_tl { #2 }
}



%%%%%%%%%%%%%%%%%%%%%%

%\token_new:Nn \c_period_token { . }
%\token_new:Nn \c_divide_token { | }
\cs_set_eq:NN \c_period_token .
\cs_set_eq:NN \c_divide_token |

%% at(@) will be used as an end-mark of input stream
%% therefore the catcode of @ should be set to other(12)
\char_set_catcode_other:N \@
%\token_new:Nn \c_tmpend_token { @ }
\cs_set_eq:NN \c_tmpend_token @

\tl_new:N \hnhg_output_tl
\tl_new:N \hnhg_output_com_tl
\tl_new:N \hnhg_long_str

\int_new:N \i_cnt
\int_new:N \j_cnt

\cs_new:Npn \hnhg_takepara:n #1
{
	\token_if_eq_charcode:NNTF #1 \c_tmpend_token
	{
		\tl_put_right:Nn \hnhg_long_str { }
	  	\exp_args:NNnx \seq_set_split:Nnn \l_takepara_seq { \c_divide_token } { \tl_use:N \hnhg_long_str }
		\int_set:Nn \j_cnt { \seq_count:N \l_takepara_seq }
		\int_zero:N \i_cnt
		\seq_map_inline:Nn \l_takepara_seq
		{
			\int_incr:N \i_cnt
			\hnhg_procword ( ##1 )
			\int_compare:nF { \i_cnt = \j_cnt }
			{ \space }
		}
	}
	{
		\tl_put_right:Nn \hnhg_long_str { #1 }
		\peek_catcode:NTF \c_space_token
		{ \tl_put_right:Nn \hnhg_long_str { \c_divide_token }
		  \hnhg_takepara:n }
		{ \hnhg_takepara:n }
	}
}

\NewDocumentCommand \hnhg_grra {  }
{
	\tl_clear:N \hnhg_output_tl
	\tl_clear:N \hnhg_output_com_tl
	\tl_clear:N \grsp_tl
	\grsp_spc:n
}

\cs_new:Npn \grsp_spc:n #1
{
	\peek_catcode:NTF \c_space_token
	{
		\tl_put_right:Nn \grsp_tl { #1 } 
		\exp_args:Nx \hnhg_takeword:n { \tl_use:N \grsp_tl }
	}
	{ \tl_put_right:Nn \grsp_tl { #1 } \grsp_spc:n }
}

\cs_new:Npn \hnhg_takeword:n #1
{
	\hnhg_procword ( #1 )
}

\NewDocumentCommand \hnhg_procword { d() }
{
	\hnhg_grra:n #1@ \q_recursion_tail \q_recursion_stop
}

\bool_new:N \flush_hanja_cluster
\bool_new:N \is_hanja_bool

%% is this character a hanja?
\cs_new:Npn \is_hanja_check:n #1
{
	\str_set_convert:Nnnn \l_tmpa_tl { #1 } { } { clist }
	\bool_if:nTF
	{
%% 13312(x3400)--40959(x9FFF): 한중일 통합한자 확장 A, 한중일 통합한자
	  ( \int_compare_p:n { \l_tmpa_tl >= 13312 } && \int_compare_p:n { \l_tmpa_tl <= 40959 } ) 
	  ||
%% 63744(xF900)--64255(xFAFF): 한중일 호환한자
	  ( \int_compare_p:n { \l_tmpa_tl >= 63744 } && \int_compare_p:n { \l_tmpa_tl <= 64255 } )
	  || 
%% 131072(x20000)--195103(x2FA1F) : 한중일 통합한자 확장 B, C, D, 보충
	  ( \int_compare_p:n { \l_tmpa_tl >= 131072 } && \int_compare_p:n { \l_tmpa_tl <= 195103 } )
%%% [와 ]
	  ||
	  ( \int_compare_p:n { \l_tmpa_tl = 91 } ) || ( \int_compare_p:n { \l_tmpa_tl = 93 } )
	}
	{ \bool_set_true:N \is_hanja_bool  }
	{ \bool_set_false:N \is_hanja_bool }
}

\bool_new:N \ignore_mode_bool

\cs_new:Npn \hnhg_grra:n #1
{
	\quark_if_recursion_tail_stop:n #1
	
	\str_case:nn { #1 }
	{
		{ [ } { \bool_set_true:N \ignore_mode_bool }
		{ ] } { \bool_set_false:N \ignore_mode_bool }
	}

	\is_hanja_check:n { #1 }
	\bool_if:nTF { ( \is_hanja_bool ) || ( \ignore_mode_bool ) }
	{
		\bool_set_true:N \flush_hanja_cluster
		\tl_put_right:Nn \hnhg_output_tl { #1 }
	}
	{
		\bool_if:NT \flush_hanja_cluster
		{
			\exp_args:Nx \rwhanja { \tl_use:N \hnhg_output_tl } 
			\tl_clear:N \hnhg_output_tl
			\bool_set_false:N \flush_hanja_cluster
		}
		\token_if_eq_charcode:NNF #1 @ { #1 }
	}
	\hnhg_grra:n
}

%\NewDocumentCommand \rpSetReading { m }
%{
%	\clist_set:Nn \l_tmp_clist { #1 }
%	\clist_map_inline:Nn \l_tmp_clist
%	{
%		\tl_if_in:nnTF { ##1 } { * }
%		{ \__divide_arg_rp_star:w ##1 \q_stop }
%		{ \__divide_arg_rp:w ##1 \q_stop }
%	}
%}
%
%\cs_new:Npn \__divide_arg_rp:w #1 = #2 \q_stop
%{
%	\AssignReading  { #1 } { #2 }
%}
%
%\cs_new:Npn \__divide_arg_rp_star:w #1 = #2 * \q_stop
%{
%	\AssignReading*  { #1 } { #2 }
%}

\NewDocumentCommand \rpRead { m o }
{
	\IfValueT { #2 } { \rpSetReading { #2 } }
	\use:c { rphanja #1 }
}

\def\rphanjapara#1\par{ 
	\tl_clear:N \hnhg_long_str 
	\hnhg_takepara:n #1\c_tmpend_token \par 
}

\def\rphanjaperiod#1.{
	\tl_clear:N \hnhg_long_str
	\hnhg_takepara:n #1\c_tmpend_token .
}

\def\rphanjacomma#1,{
	\tl_clear:N \hnhg_long_str
	\hnhg_takepara:n #1\c_tmpend_token ,
}

\def\rphanjaat#1@{
	\tl_clear:N \hnhg_long_str
	\hnhg_takepara:n #1\c_tmpend_token
}

%%%%%%%%%%%%%%%%%%%%

\cs_new:Npn \__code_point:nn #1 #2
{
%	\str_set_convert:Nnnn \code_point_view_tl { #1 } { } { utf16be/hex }
	\str_set_convert:Nnnn \code_point_view_tl { #1 } { } { #2 }
}

\NewDocumentCommand \viewCodePoint { s m }
{
	\IfBooleanTF { #1 }
	{
		\__code_point:nn { #2 } { clist }
	}
	{
		\__code_point:nn { #2 } { utf16be/hex }
	}
	#2 \fbox { \tl_use:N \code_point_view_tl }
}

%\NewDocumentCommand \hnjahngldrafton {}
%{
%	\bool_set_true:N \g_dispallhangul_bool
%}
%
%\NewDocumentCommand \hnjahngldraftoff {}
%{
%	\bool_set_false:N \g_dispallhangul_bool
%}

\NewDocumentCommand \showAltReadings { m }
{
	\tl_set:Nn \l_tmpa_tl { #1 }
	\regex_replace_all:nnN { (.) } { \1, } \l_tmpa_tl
	\regex_replace_all:nnN { \,\[\,(.)\,\] } { \[\1\] } \l_tmpa_tl
	
	\exp_args:NNx \seq_set_from_clist:Nn \l_tmpa_seq { \l_tmpa_tl }
	
	\seq_map_inline:Nn \l_tmpa_seq
	{
		\str_if_in:nnTF { ##1 } { [ }
		{
			\_show_altread_fn:w ##1 \q_stop
		}
		{
			\_show_altread_fn:w ##1 [ 0 ] \q_stop
		}
		
		\exp_args:No \__read_hanja_ons:n { \l_hanjacode_tl }
		
		\tl_clear:N \l_hanglcode_tl
		
		\seq_indexed_map_function:NN \l_read_seq \showaltread_fn:nn
		
		\tl_if_empty:NF \l_readtxt_tl 
		{
			\tl_put_right:Nx \l_hanglcode_tl { *\l_readtxt_tl }
		}
		
		\group_begin:
		\fboxsep=1pt \grrubystyle{rup}
		\hnjahnglgrfoo \l_hanglcode_tl ( \l_hanjacode_tl ) \relax
		\group_end:

	}
}

\cs_set_eq:NN \showReadings \showAltReadings

\cs_new:Npn \showaltread_fn:nn #1 #2
{
	\int_compare:nTF { #1 - 1 == \l_readidx_int }
	{
		\tl_put_right:Nx \l_hanglcode_tl { \exp_not:N \fbox { \symbol{ #2 } } }
	}
	{
		\tl_put_right:Nx \l_hanglcode_tl { \symbol { #2 } }
	}
}

\cs_new:Npn \__read_hanja_ons:n #1
{
	\__get_codepoint_fn:nN { #1 } \l_code_tl
	
	\__get_hnglcode_from_file:nnN { \l_code_tl } { hanja2hangul.dat } \l_read_seq
}

\cs_new:Npn \_show_altread_fn:w #1 [ #2 ] \q_stop
{
	\tl_set:Nn \l_hanjacode_tl { #1 }
	\tl_clear:N \l_readtxt_tl
	
	\regex_match:nnTF { \D } { #2 }
	{
		\int_set:Nn \l_readidx_int { 0 }
		\tl_set:Nn \l_readtxt_tl { #2 }
	}
	{
		\int_set:Nn \l_readidx_int { #2 }
	}
}

%%% for manual document
\tl_gset:Nn \hnjahnglpkgdate { 2023/02/27 }
\tl_gset:Nn \hnjahnglpkgversion { v1.3 }

%%% for debugging
\NewDocumentCommand \PrintAllUsedHanja {}
{
	\prop_map_inline:Nn \l_usedhanja_prop
	{
		\symbol{##1}, \c_space_token
	}
	\par
}

\endinput
