*/}}
Browse Source

ime and various code page fixes

YimingWu 2 months ago
parent
commit
935eb2ad7b

+ 2 - 0
CMakeLists.txt

@@ -77,6 +77,8 @@ embed_resource("resources/soft_proof_table_Clay.lagui.lut" "BuildResources/soft_
 embed_resource("resources/soft_proof_table_D65P3.lagui.lut" "BuildResources/soft_proof_table_D65P3.lagui.lut.c" "DATA_LUT_PROOF_D65P3")
 
 add_compile_options("$<$<C_COMPILER_ID:MSVC>:/std:c11>")
+add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
+add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
 
 file(GLOB SOURCE_FILES 
 	./*.c ./*.cpp ./resources/*.c ./resources/*.cpp BuildResources/*.c)

+ 5 - 0
la_interface.h

@@ -134,6 +134,7 @@
 
 #define LA_KEY_PANNING    (1<<26)
 
+#define LA_PASTE    (1<<29)
 #define LA_OPERATOR_EVENT (1<<30)
 #define LA_SIGNAL_EVENT   (1<<31)
 
@@ -404,6 +405,7 @@ STRUCTURE(LA){
 
     char *InputBuf; int InputBufNext, InputBufMax;
     int32_t *InputBufU; int InputBufUNext, InputBufUMax;
+    laSafeString* PasteString;
 #ifdef LA_LINUX
     Atom MsgDelWindow;
     Atom bufid;
@@ -731,6 +733,7 @@ STRUCTURE(laWindow){
     struct NVGcontext* nvg;
 #ifdef _WIN32
     HDC hdc;
+    HIMC himc;
 #endif
 
     int X,Y,W,H;
@@ -2724,6 +2727,8 @@ void laui_DefaultPropUiDefine(laUiList *uil, laPropPack *This, laPropPack *Opera
 void laui_PropOperatorUiDefine(laUiList *uil, laPropPack *This, laPropPack *Unused, laColumn *UNUSED, int context);
 
 int laCopyToClipboard(unsigned char * text);
+void laDisableIME(laWindow* w);
+void laEnableIME(laWindow* w);
 
 #ifdef LAGUI_ANDROID
 bool la_check_permission(const char* permission);

+ 51 - 16
la_kernel.c

@@ -590,6 +590,7 @@ int la_CreateSystemWindow(laWindow *window, int SyncToVBlank){
     RECT rc; GetClientRect(window->win, &rc);
     window->CW = rc.right - rc.left;
     window->CH = rc.bottom - rc.top;
+    window->himc = ImmCreateContext();
 #endif
 #ifdef LA_LINUX
     XWindowAttributes attr;
@@ -668,8 +669,15 @@ void laRenameWindow(laWindow* wnd, char* name){
     XStoreName(MAIN.dpy, wnd->win, name);
 #endif
 #ifdef _WIN32
-    //wchar_t buf[128]; MultiByteToWideChar(CP_UTF8, 0, name, -1, buf, 128);
-    SetWindowTextW(wnd->win, name);
+    int wlen=strlen(name)+1;
+    int unisize=MultiByteToWideChar(CP_UTF8, 0, name, -1, 0, 0);
+    WCHAR *unistr=malloc(wlen*sizeof(WCHAR));
+    MultiByteToWideChar(CP_UTF8, 0, name, -1, unistr, unisize);
+    int bufsize=WideCharToMultiByte(CP_ACP, 0, unistr, -1, 0, 0, 0, 0);
+    char* acpstr = malloc(bufsize);
+    WideCharToMultiByte(CP_ACP, 0, unistr, -1, acpstr, bufsize, 0, 0);
+    SetWindowText(wnd->win, acpstr);
+    free(unistr); free(acpstr);
 #endif
 }
 
@@ -2173,6 +2181,11 @@ void la_SendSignalEvent(SYSWINDOW* hwnd, int signal){
     e->key = signal;
     la_SaveEvent(hwnd, e, 1);
 };
+void la_SendPasteEvent(SYSWINDOW* hwnd) {
+    laEvent* e = memAcquireSimple(sizeof(laEvent));
+    e->type = LA_PASTE;
+    la_SaveEvent(hwnd, e, 1);
+};
 void la_SendOperatorEvent(SYSWINDOW* hwnd, laOperatorType* at, int use_base, char* instructions){
     if(!at){ return; }
     laEvent *e = memAcquireSimple(sizeof(laEvent));
@@ -3871,6 +3884,7 @@ laPanel *laDesignPropPanel(char *Title, int X, int Y, int W, int H,
     strSafeSet(&p->Title, Title);
 
     if (Define){
+        if (!This) { This = &p->PP; }
         Define(laPrepareUi(p), This, OperatorProps, NULL, 0);
     }
 
@@ -7989,11 +8003,11 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
         break;
 
     case WM_SYSKEYDOWN:
-        if (lparam & 0x40000000) break;
+        //if (lparam & 0x40000000) break;
         la_SendKeyboardEvent(hwnd, LA_KEY_DOWN, la_TranslateSpecialKey(wparam));
         break;
     case WM_KEYDOWN:
-        if (lparam & 0x40000000) break;
+        //if (lparam & 0x40000000) break;
         vkey = wparam;
         la_SendKeyboardEvent(hwnd, LA_KEY_DOWN, la_TranslateSpecialKey(vkey));
         break;
@@ -8007,7 +8021,9 @@ LRESULT CALLBACK LA_WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lp
         la_SendInputEvent(hwnd, wparam);
         break;
     case WM_IME_CHAR:
-        la_SendInputEvent(hwnd, wparam);
+        char character[3]; character[0]=(BYTE)(wparam>>8); character[1] = wparam; character[2]=0;
+        wchar_t buf[10]; MultiByteToWideChar(CP_ACP, 0, character, -1, buf, 9);
+        la_SendInputEvent(hwnd, buf[0]);
         return 0;
     case WM_CHAR:
         la_SendInputEvent(hwnd, wparam);
@@ -8165,6 +8181,7 @@ int la_HandleSingleEvent(laEvent *e, laListHandle *Operators){
             a->ConfirmData = NextConfirmData;
         }
     }
+    if (e->type==LA_PASTE && MAIN.PasteString) strSafeDestroy(&MAIN.PasteString);
     return 1;
 }
 int la_HandleEvents(laWindow *w){
@@ -8212,7 +8229,7 @@ int la_HandleEvents(laWindow *w){
     la_UpdateOperatorHints(w);
     return 1;
 }
-int la_AllowInput(uint32_t ch){
+int la_AccpetedUnicodeInput(uint32_t ch){
     if(ch>=32 || ch==U'\n' || ch==U'\t' || ch==U'\b') return 1;
     return 0;
 }
@@ -8223,9 +8240,31 @@ int laCopyToClipboard(unsigned char * text){
 	if (XGetSelectionOwner (MAIN.dpy, MAIN.selection) != window) return 0;
     strSafeSet(&MAIN.CopyPending, text);
     return 1;
+#endif
+#ifdef _WIN32
+    OpenClipboard(GetDesktopWindow());
+    EmptyClipboard();
+    size_t allocsize = strlen(text) + 1;
+    HGLOBAL hg = GlobalAlloc(GMEM_MOVEABLE, allocsize);
+    if (!hg){ CloseClipboard(); return; }
+    memcpy(GlobalLock(hg), text, allocsize);
+    GlobalUnlock(hg);
+    SetClipboardData(CF_TEXT, hg);
+    CloseClipboard();
+    GlobalFree(hg);
 #endif
     return 0;
 }
+void laDisableIME(laWindow* w) {
+#ifdef _WIN32
+    ImmAssociateContext(w->win, 0);
+#endif
+}
+void laEnableIME(laWindow* w) {
+#ifdef _WIN32
+    if(w->himc) ImmAssociateContext(w->win, w->himc);
+#endif
+}
 int la_ProcessSysMessage(){
     int SendDelay = 0, SendIdle = 0;
     if (!MAIN.DelayTriggered && MAIN.TimeAccum - MAIN.DelayStart > MAIN.DelayTime) SendDelay = 1;
@@ -8287,7 +8326,7 @@ int la_ProcessSysMessage(){
                 if (InputStatus==XBufferOverflow)  printf("XInputBufferOverflow\n");
                 if (InputStatus == XLookupKeySym || InputStatus == XLookupBoth) { /*printf("status: %d\n", InputStatus);*/ }
             if (InputCount){ MAIN.InputBuf[InputCount]=0; } strToUnicode(MAIN.InputBufU,MAIN.InputBuf); int UCount=strlenU(MAIN.InputBufU);
-            for(int i=0;i<UCount;i++){ if(la_AllowInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }
+            for(int i=0;i<UCount;i++){ if(la_AccpetedUnicodeInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }
             XKeyboardState x; XGetKeyboardControl(MAIN.dpy, &x);
             int numlock=0; if(x.led_mask & 2){ numlock=1; }
             if(InputKeysym=XkbKeycodeToKeysym(e.xkey.display, e.xkey.keycode, 0, 0)){
@@ -8317,12 +8356,7 @@ int la_ProcessSysMessage(){
                 &fmtid, &resbits, &ressize, &restail, (unsigned char**)&result);
 
                 if (fmtid == MAIN.incrid) logPrintNew("Pasted buffer is too large and INCR reading is not implemented yet.\n");
-                else if(result) {
-                    arrEnsureLength(&MAIN.InputBufU, strlen(result), &MAIN.InputBufUMax, sizeof(uint32_t));
-                    strToUnicode(MAIN.InputBufU,result); int UCount=strlenU(MAIN.InputBufU);
-                    for(int i=0;i<UCount;i++){ if(la_AllowInput(MAIN.InputBufU[i])) la_SendInputEvent(e.xkey.window, MAIN.InputBufU[i]); }
-                }
-
+                else if(result) { strSafeSet(&MAIN.PasteString,result); }
                 XFree(result);
                 return True;
             }
@@ -8356,9 +8390,9 @@ int la_ProcessSysMessage(){
     if (PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE) != 0) Processed = 1;
 
     while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {
-        if (msg.wParam == VK_PROCESSKEY) {
-            msg.wParam = ImmGetVirtualKey(msg.hwnd);
-        }
+        //if (msg.wParam == VK_PROCESSKEY) {
+        //    msg.wParam = ImmGetVirtualKey(msg.hwnd);
+        //}
         TranslateMessage(&msg); DispatchMessage(&msg);
         SendIdle = 0; MAIN.IdleStart = MAIN.TimeAccum; MAIN.IdleTriggered = 0;
     };
@@ -9215,6 +9249,7 @@ void la_request_permission(const char* permission) {
 
 #ifndef LAGUI_ANDROID
 void la_DisplayKeyboard(bool pShow) {
+    if(pShow){ laEnableIME(MAIN.CurrentWindow); } else { laDisableIME(MAIN.CurrentWindow); }
     return;
 }
 void la_HideNavBar(){

+ 1 - 0
la_util.c

@@ -2013,6 +2013,7 @@ char* strGetEditString(laStringEdit *se, int SelectionOnly){
     return result;
 }
 char* strEndEdit(laStringEdit **se, int FreeString){
+    laDisableIME(MAIN.CurrentWindow);
     char *p=0; laStringLine *sl, *NextSl;
     if (!se || !(*se)) return 0;
     p=strGetEditString(*se, 0);

+ 17 - 1
resources/la_operators.c

@@ -67,6 +67,7 @@ void la_EnsurePanelSnapping(laPanel *p, int CW, int CH);
 void la_RecalcBlockRecursive(laBlock *b, int X, int Y, int W, int H);
 void la_ConditionNodeFreeRecursive(laUiConditionNode *ucn);
 void la_SendSignalEvent(SYSWINDOW* hwnd, int signal);
+void la_SendPasteEvent(SYSWINDOW* hwnd);
 
 int OPMOD_FinishOnData(laOperator* a, laEvent* e){
     if(a->ConfirmData){
@@ -1989,7 +1990,7 @@ int OPINV_SwitchLayout(laOperator *a, laEvent *e){
     else newlayout = w->CurrentLayout->Item.pNext ? w->CurrentLayout->Item.pNext : w->Layouts.pFirst;
     memAssignRef(w, &w->CurrentLayout, newlayout);
 
-    laRenameWindow(w, w->CurrentLayout->ID->Ptr);
+    laRenameWindow(w, SSTR(w->CurrentLayout->ID));
 
     la_StopAllOperators();
     laRetriggerOperators();
@@ -2049,6 +2050,21 @@ void la_GeneratePasteEvent(laWindow* w){
 #ifdef LA_LINUX
     XConvertSelection(MAIN.dpy, MAIN.bufid, MAIN.fmtid, MAIN.propid, w->win, CurrentTime);
 #endif
+#ifdef _WIN32
+    if (!MAIN.CurrentWindow) return;
+    if (!IsClipboardFormatAvailable(CF_TEXT)) return;
+    if (!OpenClipboard(GetDesktopWindow())) return;
+    HGLOBAL hg = GetClipboardData(CF_TEXT);
+    if(hg){
+        LPCSTR strData = (LPCSTR)GlobalLock(hg);
+        if (strData) {
+            strSafeSet(&MAIN.PasteString, strData);
+            la_SendPasteEvent(MAIN.CurrentWindow->win);
+            GlobalUnlock(hg);
+        }
+    }
+    CloseClipboard();
+#endif
 }
 int OPINV_SystemPaste(laOperator *a, laEvent *e){ la_GeneratePasteEvent(MAIN.CurrentWindow); return LA_FINISHED; }
 int OPINV_Window(laOperator *a, laEvent *e){

+ 2 - 1
resources/la_properties.c

@@ -389,7 +389,7 @@ void laget_LayoutTitle(laLayout *l, char *result, char** result_direct){
 }
 void laset_LayoutTitle(laLayout *l, char *content){
     strSafeSet(&l->ID, content);
-    if(l->ID->Ptr) laRenameWindow(MAIN.CurrentWindow, l->ID->Ptr);
+    laRenameWindow(MAIN.CurrentWindow, SSTR(l->ID));
 }
 //void* laget_LayoutPanelFirst(laLayout* l) {
 //	return l->Panels.pFirst;
@@ -680,6 +680,7 @@ void laget_PanelTemplateCategory(void* rack_unused, laUiTemplate* uit, char* cop
 
 void lapost_Window(laWindow *w){
     laStartWindow(w);
+    laDisableIME(w);
 }
 int la_CreateSystemWindow(laWindow *window, int synctovbank);
 void la_AssignWindowPP(laWindow* w);

+ 4 - 5
resources/la_templates.c

@@ -37,7 +37,7 @@ void laui_DefaultPropDetails(laUiList *uil, laPropPack *This, laPropPack *Extra,
         if(This&&This->LastPs&&This->EndInstance){
             laProp* p=This->LastPs->p; laPropContainer* pc=p->Container; void* inst=This->LastPs->UseInstance; 
             char FullPath[256]={0}; la_GetPropPackFullPath(This, FullPath);
-            strSafePrint(&s,"%s", FullPath); if(ui->ExtraInstructions){ strSafePrint(&s,"(%s)", ui->ExtraInstructions->Ptr); }
+            strSafePrint(&s,"%s", FullPath); if(ui->ExtraInstructions){ strSafePrint(&s,"(%s)", SSTR(ui->ExtraInstructions)); }
             laShowLabel(uil,c,p->Name,0,0);
             laShowSeparator(uil,c);
             laShowLabel(uil,c,p->Description,0,0)->Flags|=LA_TEXT_LINE_WRAP;
@@ -46,7 +46,7 @@ void laui_DefaultPropDetails(laUiList *uil, laPropPack *This, laPropPack *Extra,
             laShowLabel(uil,c,ui->AT->Name,0,0);
             laShowSeparator(uil,c);
             laShowLabel(uil,c,ui->AT->Description,0,0)->Flags|=LA_TEXT_LINE_WRAP;
-            strSafePrint(&s,"%s", ui->AT->Identifier); if(ui->ExtraInstructions){ strSafePrint(&s,"(%s)", ui->ExtraInstructions->Ptr); }
+            strSafePrint(&s,"%s", ui->AT->Identifier); if(ui->ExtraInstructions){ strSafePrint(&s,"(%s)", SSTR(ui->ExtraInstructions)); }
             laShowLabel(uil,c,s->Ptr,0,0)->Flags|=LA_TEXT_MONO|LA_UI_FLAGS_DISABLED;
         }
     }else{
@@ -1411,8 +1411,10 @@ void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorIn
             laShowItem(muil, mcr, &UP->PP, "font_size");
             laShowLabel(muil, mcl, "Margin Size:", 0, 0);
             laShowItem(muil, mcr, &UP->PP, "margin_size");
+#ifndef LA_USE_GLES
             laShowLabel(muil, mcl, "Panel Multisample:", 0, 0);
             laShowItem(muil, mcr, &UP->PP, "panel_multisample")->Flags|=LA_UI_FLAGS_EXPAND;
+#endif
             laShowLabel(muil, mcl, "Top Framerate:", 0, 0);
             laShowItem(muil, mc, &UP->PP, "top_framerate");
 
@@ -1469,9 +1471,6 @@ void laui_UserPreference(laUiList *uil, laPropPack *Base, laPropPack *OperatorIn
             laShowSeparator(muil,mc);
 
             laShowLabel(muil, mc, "Input device handling:", 0, 0);
-#ifdef _WIN32
-            laShowLabel(muil, mc, "Not yet implemened on Windows.", 0, 0);
-#endif
             laShowLabel(muil, mcl, "Input Mapping:", 0, 0)->Flags|=LA_TEXT_ALIGN_RIGHT;
             laShowItemFull(muil, mcr, 0, "LA_panel_activator",0,"panel_id=LAUI_input_mapping;text=Configure",0,0);
             laShowLabel(muil, mcl, "Pads/Joysticks:", 0, 0)->Flags|=LA_TEXT_ALIGN_RIGHT;

+ 0 - 1
resources/la_translations_es-ES.c

@@ -300,7 +300,6 @@ static const char *entries[]={
 "Move Left","Mueve a la Izquierda",
 "Move Right","Mueve a la Derecha",
 "Driver:","Driver:",
-"Not yet implemened on Windows.","Aún no está implementado en Windows.",
 "Set Min","Establecer Mínimo",
 "Set Max","Establecer Máximo",
 "Restore Default","Restaurar Defecto",

+ 0 - 1
resources/la_translations_zh-hans.c

@@ -295,7 +295,6 @@ static const char *entries[]={
 "Move Left","向左移动",
 "Move Right","向右移动",
 "Driver:","驱动程序:",
-"Not yet implemened on Windows.","尚未在Windows上实现。",
 "Set Min","调成最小",
 "Set Max","调成最大",
 "Restore Default","恢复默认值",

+ 17 - 5
resources/la_widgets.c

@@ -2353,6 +2353,7 @@ int OPINV_EditStringCopySelection(laOperator *a, laEvent *e){
     return LA_FINISHED;
 }
 
+int la_AccpetedUnicodeInput(uint32_t ch);
 int la_ProcessTextEdit(laEvent *e, laStringEdit *se, laUiItem* ui){
     int Select=e->SpecialKeyBit&LA_KEY_SHIFT;
     real _L, MonoWidth;
@@ -2363,9 +2364,14 @@ int la_ProcessTextEdit(laEvent *e, laStringEdit *se, laUiItem* ui){
         case 0x7f: if(strHasSelection(se)) strClearSelection(se); else { strMoveCursor(se,0,0); strBackspace(se); } return 1;
         case 0x09: strInsertChar(se, ' ');strInsertChar(se, ' ');strInsertChar(se, ' ');strInsertChar(se, ' '); return 1;
         case 0x1B: case 0x0D: return 0;
-        default: strInsertChar(se, e->Input); return 1;
+        default: if(e->Input>=32) strInsertChar(se, e->Input); return 1;
         }
         break;
+    case LA_PASTE:
+        unsigned char* pasted=MAIN.PasteString?MAIN.PasteString->Ptr:0; if(!pasted) break;
+        uint32_t uni = 0, adv = 0;
+        while(uni=laToUnicode(pasted,&adv)){ pasted+=adv; if(la_AccpetedUnicodeInput(uni)){ strInsertChar(se, uni); } }
+        return 1;
     case LA_KEY_DOWN:
         switch (e->key){
         case LA_KEY_ENTER: strInsertChar(se, '\n'); return 1;
@@ -3174,7 +3180,7 @@ int OPMOD_MultiString(laOperator *a, laEvent *e){
         if ((e->type & LA_MOUSEDOWN) == LA_MOUSEDOWN){
             buf=strGetEditString(es->Edit, 0); laSetString(&ui->PP, buf); free(buf);
             laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
-            ui->State = LA_UI_NORMAL;
+            ui->State = LA_UI_NORMAL; la_DisplayKeyboard(0);
             laRedrawCurrentPanel();
             return LA_FINISHED_PASS;
         }
@@ -3194,7 +3200,7 @@ int OPMOD_MultiString(laOperator *a, laEvent *e){
             if(ui->State != LA_UI_NORMAL){
                 buf=strGetEditString(es->Edit, 0); laSetString(&ui->PP, buf); free(buf);
                 laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
-                ui->State = LA_UI_NORMAL; laRedrawCurrentPanel();la_SetMultistringViewRange(ui,es->Edit,bt);
+                ui->State = LA_UI_NORMAL; laRedrawCurrentPanel(); la_SetMultistringViewRange(ui,es->Edit,bt); la_DisplayKeyboard(0);
             }
             if(es->Dragging){ es->Dragging=0; es->HeightCoeff=es->TargetIndexVali; laRecalcCurrentPanel();la_SetMultistringViewRange(ui,es->Edit,bt); }
             return LA_FINISHED;
@@ -3227,7 +3233,7 @@ int OPMOD_MultiString(laOperator *a, laEvent *e){
             ui->State = LA_UI_ACTIVE;
             laGetString(&ui->PP, _buf, &buf);
             strBeginEdit(&es->Edit,buf);la_SetMultistringViewRange(ui,es->Edit,bt);
-            laRedrawCurrentPanel();
+            laRedrawCurrentPanel(); la_DisplayKeyboard(1);
             return LA_RUNNING;
         }
     }
@@ -3381,7 +3387,13 @@ int OPMOD_CollectionSelector(laOperator *a, laEvent *e){
     int ReadOnly=laIsPropertyReadOnly(&ui->PP);
     int Simple=ui->Flags&LA_UI_COLLECTION_SIMPLE_SELECTOR;
 
-    if (laConfirmSameDataIfAny(a)){
+    if(ui->Flags & LA_UI_FLAGS_NO_CONFIRM){
+        if (a->ConfirmData) {
+            ui->State = LA_UI_NORMAL;
+            laRecalcCurrentPanel();
+            return LA_RUNNING_PASS;
+        }
+    }elif (laConfirmSameDataIfAny(a)){
         ui->State = LA_UI_NORMAL;
         laRecalcCurrentPanel();
         return LA_RUNNING_PASS;