From 58dd0198ddf9143942a9819c4864b0c24afa306e Mon Sep 17 00:00:00 2001 From: Megamouse Date: Sat, 20 Jan 2024 17:31:56 +0100 Subject: [PATCH] cellImeJp: add candidate list functions --- rpcs3/Emu/Cell/Modules/cellImeJp.cpp | 71 ++++++++++++++++++++++++++-- rpcs3/Emu/Cell/Modules/cellImeJp.h | 8 ++++ 2 files changed, 76 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellImeJp.cpp b/rpcs3/Emu/Cell/Modules/cellImeJp.cpp index 4439fbd73c..f0bf2636f5 100644 --- a/rpcs3/Emu/Cell/Modules/cellImeJp.cpp +++ b/rpcs3/Emu/Cell/Modules/cellImeJp.cpp @@ -181,6 +181,30 @@ void ime_jp_manager::move_focus_end(s8 amount, bool wrap_around) focus_length = std::max(min_length, std::min(max_length, focus_length)); } +std::vector ime_jp_manager::get_candidate_list() const +{ + std::vector candidates; + if (input_string.empty() || focus_length == 0 || focus_begin >= input_string.length()) + return candidates; + + // TODO: we just fake this with one candidate for now + candidates.push_back(candidate{ + .text = get_focus_string(), + .offset = 0 + }); + + return candidates; +} + +std::u16string ime_jp_manager::get_focus_string() const +{ + if (input_string.empty() || focus_length == 0 || focus_begin >= input_string.length()) + return {}; + + return input_string.substr(focus_begin, focus_length); +} + + static error_code cellImeJpOpen(sys_memory_container_t container_id, vm::ptr hImeJpHandle, vm::cptr addDicPath) { cellImeJp.todo("cellImeJpOpen(container_id=*0x%x, hImeJpHandle=*0x%x, addDicPath=*0x%x)", container_id, hImeJpHandle, addDicPath); @@ -904,7 +928,7 @@ static error_code cellImeJpGetFocusLength(CellImeJpHandle hImeJpHandle, vm::ptr< return CELL_IMEJP_ERROR_CONTEXT; } - *pFocusLength = ::narrow(manager.focus_length) * 2; // offset in bytes + *pFocusLength = ::narrow(manager.focus_length * 2); // offset in bytes return CELL_OK; } @@ -1059,7 +1083,18 @@ static error_code cellImeJpGetCandidateListSize(CellImeJpHandle hImeJpHandle, vm return CELL_IMEJP_ERROR_ERR; } - *pListSize = 0; + // Add focus string size, including null terminator + const std::u16string focus_string = manager.get_focus_string(); + usz size = sizeof(u16) * (focus_string.length() + 1); + + // Add candidates, including null terminators and offsets + for (const ime_jp_manager::candidate& can : manager.get_candidate_list()) + { + constexpr usz offset_size = sizeof(u16); + size += offset_size + (can.text.size() + 1) * sizeof(u16); + } + + *pListSize = ::narrow(size); return CELL_OK; } @@ -1086,7 +1121,37 @@ static error_code cellImeJpGetCandidateList(CellImeJpHandle hImeJpHandle, vm::pt return CELL_IMEJP_ERROR_ERR; } - *plistNum = 0; + // First, copy the focus string + u32 pos = 0; + const std::u16string focus_string = manager.get_focus_string(); + for (u32 i = pos; i < focus_string.length(); i++) + { + pCandidateString[i] = focus_string[i]; + } + pos += ::narrow(focus_string.length()); + + // Add null terminator + pCandidateString[pos++] = 0; + + // Add list of candidates + const std::vector list = manager.get_candidate_list(); + for (const ime_jp_manager::candidate& can : list) + { + // Copy the candidate + for (u32 i = pos; i < can.text.length(); i++) + { + pCandidateString[i] = can.text[i]; + } + pos += ::narrow(can.text.length()); + + // Add null terminator + pCandidateString[pos++] = 0; + + // Add offset + pCandidateString[pos++] = can.offset; + } + + *plistNum = ::narrow(list.size()); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellImeJp.h b/rpcs3/Emu/Cell/Modules/cellImeJp.h index 9efa7d3abe..9d332e89f3 100644 --- a/rpcs3/Emu/Cell/Modules/cellImeJp.h +++ b/rpcs3/Emu/Cell/Modules/cellImeJp.h @@ -136,4 +136,12 @@ struct ime_jp_manager void move_cursor(s8 amount); // s8 because CELL_IMEJP_STRING_MAXLENGTH is 128 void move_focus(s8 amount); // s8 because CELL_IMEJP_STRING_MAXLENGTH is 128 void move_focus_end(s8 amount, bool wrap_around); // s8 because CELL_IMEJP_STRING_MAXLENGTH is 128 + + struct candidate + { + std::u16string text; // Actual text of the candidate + u16 offset = 0; // The offset of the next character after the candidate replaced part of the current focus. + }; + std::vector get_candidate_list() const; + std::u16string get_focus_string() const; };