122 lines3.2 KBC
1/*
2osk_ps3.c: the system's on-screen keyboard (sysutil OSK), for Search.
3As PSL1GHT's samples/sys/osk: load it into its own memory container, keep
4flipping (the system draws it over our frames), and collect the text when
5the sysutil callback says it's done.
6*/
7#include <stdio.h>
8#include <string.h>
9#include <sys/memory.h>
10#include <sysutil/osk.h>
11#include <sysutil/sysutil.h>
12#include "../plat.h"
13#include "ps3.h"
14
15#define OSK_LEN 128
16
17static uint16_t title16[OSK_LEN], start16[OSK_LEN], result16[OSK_LEN + 1];
18static oskInputFieldInfo field;
19static oskParam param;
20static oskCallbackReturnParam ret;
21static sys_mem_container_t container;
22static volatile int state; // 0 idle, 1 open, 2 entered, 3 cancelled
23static int have_container;
24
25static void To16(const char *s, uint16_t *d, int max)
26{
27 const unsigned char *p = (const unsigned char *)s;
28 int o = 0;
29 while (*p && o < max - 1) {
30 uint32_t c = *p++;
31 if (c >= 0xe0 && p[0] && p[1]) { c = ((c & 0x0f) << 12) | ((p[0] & 0x3f) << 6) | (p[1] & 0x3f); p += 2; }
32 else if (c >= 0xc0 && p[0]) { c = ((c & 0x1f) << 6) | (p[0] & 0x3f); p += 1; }
33 d[o++] = (uint16_t)c;
34 }
35 d[o] = 0;
36}
37
38static void To8(const uint16_t *s, char *d, int size)
39{
40 int o = 0;
41 for (; *s && o < size - 4; s++) {
42 uint32_t c = *s;
43 if (c < 0x80) d[o++] = (char)c;
44 else if (c < 0x800) { d[o++] = 0xc0 | (c >> 6); d[o++] = 0x80 | (c & 0x3f); }
45 else { d[o++] = 0xe0 | (c >> 12); d[o++] = 0x80 | ((c >> 6) & 0x3f); d[o++] = 0x80 | (c & 0x3f); }
46 }
47 d[o] = 0;
48}
49
50// from main_ps3.c's sysutil callback
51void ps3_osk_event(u64 status)
52{
53 switch (status) {
54 case SYSUTIL_OSK_INPUT_CANCELED:
55 oskAbort();
56 // fall through: it still has to be unloaded
57 case SYSUTIL_OSK_DONE:
58 oskUnloadAsync(&ret);
59 break;
60 case SYSUTIL_OSK_UNLOADED:
61 state = (ret.res == OSK_OK) ? 2 : 3;
62 if (have_container) {
63 sysMemContainerDestroy(container);
64 have_container = 0;
65 }
66 break;
67 }
68}
69
70int plat_osk_open(const char *title, const char *initial)
71{
72 s32 r;
73 if (state == 1) return 0;
74 memset(result16, 0, sizeof(result16));
75 To16(title, title16, OSK_LEN);
76 To16(initial ? initial : "", start16, OSK_LEN);
77 field.message = title16;
78 field.startText = start16;
79 field.maxLength = OSK_LEN - 1;
80 param.allowedPanels = OSK_PANEL_TYPE_DEFAULT;
81 param.firstViewPanel = OSK_PANEL_TYPE_DEFAULT;
82 param.controlPoint = (oskPoint){0, 0};
83 param.prohibitFlags = OSK_PROHIBIT_RETURN;
84 ret.res = OSK_OK;
85 ret.len = OSK_LEN;
86 ret.str = result16;
87 if ((r = sysMemContainerCreate(&container, 4 * 1024 * 1024)) != 0) {
88 plat_log("osk: sysMemContainerCreate = 0x%08x", (unsigned)r);
89 return 0;
90 }
91 have_container = 1;
92 oskSetInitialInputDevice(OSK_DEVICE_PAD);
93 oskSetKeyLayoutOption(OSK_FULLKEY_PANEL);
94 oskSetLayoutMode(OSK_LAYOUTMODE_HORIZONTAL_ALIGN_CENTER | OSK_LAYOUTMODE_VERTICAL_ALIGN_CENTER);
95 if ((r = oskLoadAsync(container, &param, &field)) != 0) {
96 plat_log("osk: oskLoadAsync = 0x%08x", (unsigned)r);
97 sysMemContainerDestroy(container);
98 have_container = 0;
99 return 0;
100 }
101 state = 1;
102 return 1;
103}
104
105int plat_osk_active(void)
106{
107 return state == 1;
108}
109
110int plat_osk_poll(char *out, int size)
111{
112 if (state == 2) {
113 To8(result16, out, size);
114 state = 0;
115 return 1;
116 }
117 if (state == 3) {
118 state = 0;
119 return -1;
120 }
121 return 0;
122}