Files
bsdports/xapp/slim/files/extra-patch-utf8
2019-12-26 07:26:06 +00:00

939 lines
29 KiB
Plaintext

--- const.h.orig 2014-08-12 18:08:28.000000000 +0200
+++ const.h 2014-08-12 18:09:20.000000000 +0200
@@ -24,9 +24,6 @@
#define HIDE 0
#define SHOW 1
-#define GET_NAME 0
-#define GET_PASSWD 1
-
#define OK_EXIT 0
#define ERR_EXIT 1
--- main.cpp.orig 2014-08-12 18:08:28.000000000 +0200
+++ main.cpp 2014-08-12 18:09:20.000000000 +0200
@@ -16,6 +16,8 @@
int main(int argc, char** argv)
{
+ // We need to set the locale to get the input encoded in UTF-8
+ setlocale (LC_ALL, "");
LoginApp = new App(argc, argv);
LoginApp->Run();
return 0;
--- panel.cpp.orig 2014-08-12 18:08:28.000000000 +0200
+++ panel.cpp 2014-08-12 18:09:20.000000000 +0200
@@ -13,6 +13,7 @@
#include <poll.h>
#include <X11/extensions/Xrandr.h>
#include "panel.h"
+#include "util.h"
using namespace std;
@@ -78,6 +79,15 @@
XftColorAllocName(Dpy, visual, colormap,
cfg->getOption("session_shadow_color").c_str(), &sessionshadowcolor);
+ /* Build XIC and XIM to be able to get unicode string from keyboard events */
+ char classname = 0;
+ displayIc = NULL;
+ displayIm = XOpenIM(Dpy, NULL, &classname, &classname);
+ if(displayIm) {
+ displayIc = XCreateIC(displayIm, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+ XNResourceName, &classname,
+ XNResourceClass, &classname, NULL);
+ }
/* Load properties from config / theme */
input_name_x = cfg->getIntOption("input_name_x");
input_name_y = cfg->getIntOption("input_name_y");
@@ -91,6 +101,8 @@
input_pass_y = input_name_y;
}
+ Reset();
+
/* Load panel and background image */
string panelpng = "";
panelpng = panelpng + themedir +"/panel.png";
@@ -210,6 +222,12 @@
Visual* visual = DefaultVisual(Dpy, Scr);
Colormap colormap = DefaultColormap(Dpy, Scr);
+ if(displayIc) {
+ XDestroyIC(displayIc);
+ }
+ if(displayIm) {
+ XCloseIM(displayIm);
+ }
XftColorFree(Dpy, visual, colormap, &inputcolor);
XftColorFree(Dpy, visual, colormap, &inputshadowcolor);
XftColorFree(Dpy, visual, colormap, &welcomecolor);
@@ -289,7 +307,8 @@
XftDraw *draw = XftDrawCreate(Dpy, Win,
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
- XftTextExtents8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(message.c_str()),
+
+ XftTextExtentsUtf8(Dpy, msgfont, reinterpret_cast<const XftChar8*>(message.c_str()),
message.length(), &extents);
string cfgX = cfg->getOption("passwd_feedback_x");
@@ -300,7 +319,7 @@
int msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
OnExpose();
- SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
&msgshadowcolor, shadowXOffset, shadowYOffset);
if (cfg->getOption("bell") == "1")
@@ -312,7 +331,7 @@
OnExpose();
// The message should stay on the screen even after the password field is
// cleared, methinks. I don't like this solution, but it works.
- SlimDrawString8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y, message,
&msgshadowcolor, shadowXOffset, shadowYOffset);
XSync(Dpy, True);
XftDrawDestroy(draw);
@@ -330,9 +349,8 @@
draw = XftDrawCreate(Dpy, Root,
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
- XftTextExtents8(Dpy, msgfont,
- reinterpret_cast<const XftChar8*>(text.c_str()),
- text.length(), &extents);
+ XftTextExtentsUtf8(Dpy, msgfont,
+ reinterpret_cast<const XftChar8*>(text.c_str()), text.length(), &extents);
cfgX = cfg->getOption("msg_x");
cfgY = cfg->getOption("msg_y");
int shadowXOffset = cfg->getIntOption("msg_shadow_xoffset");
@@ -347,9 +365,8 @@
msg_y = Cfg::absolutepos(cfgY, XHeightOfScreen(ScreenOfDisplay(Dpy, Scr)), extents.height);
}
- SlimDrawString8 (draw, &msgcolor, msgfont, msg_x, msg_y,
- text,
- &msgshadowcolor,
+ SlimDrawStringUtf8(draw, &msgcolor, msgfont, msg_x, msg_y,
+ text, &msgshadowcolor,
shadowXOffset, shadowYOffset);
XFlush(Dpy);
XftDrawDestroy(draw);
@@ -383,24 +400,27 @@
}
void Panel::Cursor(int visible) {
- const char* text = NULL;
- int xx = 0, yy = 0, y2 = 0, cheight = 0;
+ const uint16_t* text = NULL;
+ int xx = 0, yy = 0, y2 = 0, cheight = 0, textLen = 0;
const char* txth = "Wj"; /* used to get cursor height */
if (mode == Mode_Lock) {
- text = HiddenPasswdBuffer.c_str();
+ text = hiddenPasswdBuffer;
+ textLen = passwdBufferLen;
xx = input_pass_x;
yy = input_pass_y;
} else {
switch(field) {
case Get_Passwd:
- text = HiddenPasswdBuffer.c_str();
+ text = hiddenPasswdBuffer;
+ textLen = passwdBufferLen;
xx = input_pass_x;
yy = input_pass_y;
break;
case Get_Name:
- text = NameBuffer.c_str();
+ text = nameBuffer;
+ textLen = nameBufferLen;
xx = input_name_x;
yy = input_name_y;
break;
@@ -411,7 +431,7 @@
XftTextExtents8(Dpy, font, (XftChar8*)txth, strlen(txth), &extents);
cheight = extents.height;
y2 = yy - extents.y + extents.height;
- XftTextExtents8(Dpy, font, (XftChar8*)text, strlen(text), &extents);
+ XftTextExtents16(Dpy, font, (XftChar16*)text, textLen, &extents);
xx += extents.width;
if(visible == SHOW) {
@@ -478,27 +498,25 @@
XClearWindow(Dpy, Win);
if (input_pass_x != input_name_x || input_pass_y != input_name_y){
- SlimDrawString8 (draw, &inputcolor, font, input_name_x, input_name_y,
- NameBuffer,
- &inputshadowcolor,
+ SlimDrawString16(draw, &inputcolor, font, input_name_x, input_name_y,
+ nameBuffer, nameBufferLen, &inputshadowcolor,
inputShadowXOffset, inputShadowYOffset);
- SlimDrawString8 (draw, &inputcolor, font, input_pass_x, input_pass_y,
- HiddenPasswdBuffer,
- &inputshadowcolor,
+ SlimDrawString16(draw, &inputcolor, font, input_pass_x, input_pass_y,
+ hiddenPasswdBuffer, passwdBufferLen, &inputshadowcolor,
inputShadowXOffset, inputShadowYOffset);
} else { /*single input mode */
switch(field) {
case Get_Passwd:
- SlimDrawString8 (draw, &inputcolor, font,
+ SlimDrawString16(draw, &inputcolor, font,
input_pass_x, input_pass_y,
- HiddenPasswdBuffer,
+ hiddenPasswdBuffer, passwdBufferLen,
&inputshadowcolor,
inputShadowXOffset, inputShadowYOffset);
break;
case Get_Name:
- SlimDrawString8 (draw, &inputcolor, font,
+ SlimDrawString16(draw, &inputcolor, font,
input_name_x, input_name_y,
- NameBuffer,
+ nameBuffer, nameBufferLen,
&inputshadowcolor,
inputShadowXOffset, inputShadowYOffset);
break;
@@ -510,35 +528,105 @@
ShowText();
}
-void Panel::EraseLastChar(string &formerString) {
+int Panel::FieldEraseLastChar(const uint16_t **buf, int *len) {
+
+ static const uint16_t emptyBuf = 0;
+ int formerTextBufferLen = 0;
+
switch(field) {
- case GET_NAME:
- if (! NameBuffer.empty()) {
- formerString=NameBuffer;
- NameBuffer.erase(--NameBuffer.end());
+ case Get_Name:
+ formerTextBufferLen = nameBufferLen;
+ if (nameBufferLen > 0) {
+ nameBufferLen--;
}
+ *buf = nameBuffer;
+ *len = nameBufferLen;
break;
- case GET_PASSWD:
- if (!PasswdBuffer.empty()) {
- formerString=HiddenPasswdBuffer;
- PasswdBuffer.erase(--PasswdBuffer.end());
- HiddenPasswdBuffer.erase(--HiddenPasswdBuffer.end());
+ case Get_Passwd:
+ formerTextBufferLen = passwdBufferLen;
+ if (passwdBufferLen > 0) {
+ passwdBufferLen--;
+ passwdBuffer[passwdBufferLen] = 0;
}
+ *buf = hiddenPasswdBuffer;
+ *len = passwdBufferLen;
+ break;
+
+ default:
+ *buf = &emptyBuf;
+ *len = 0;
break;
}
+ return formerTextBufferLen;
}
+int Panel::FieldClear(const uint16_t **buf, int *len) {
+
+ static const uint16_t emptyBuf = 0;
+ int formerTextBufferLen = 0;
+
+ switch(field) {
+ case Get_Name:
+ formerTextBufferLen = nameBufferLen;
+ nameBufferLen = 0;
+ *buf = nameBuffer;
+ *len = nameBufferLen;
+ break;
+
+ case Get_Passwd:
+ formerTextBufferLen = passwdBufferLen;
+ memset(passwdBuffer, 0, sizeof(passwdBuffer));
+ passwdBufferLen = 0;
+ *buf = hiddenPasswdBuffer;
+ *len = passwdBufferLen;
+ break;
+
+ default:
+ *buf = &emptyBuf;
+ *len = 0;
+ break;
+ }
+ return formerTextBufferLen;
+}
+
+/* Check if the input character is allowed */
+bool Panel::isUtf16CharAllowed(uint16_t c) {
+ return ((0x020 <= c && c <= 0x07E) || (0x0A0 <= c && c != 0x0AD));
+}
+
+#define SIZE_BUFFER_KEY_PRESS 64
+
bool Panel::OnKeyPress(XEvent& event) {
- char ascii;
+ int formerTextBufferLen = -1;
+ int textBufferLen = -1;
+ const uint16_t *textBuffer = NULL;
KeySym keysym;
+ int nbReadBuf = -1;
+ uint16_t utf16buf[SIZE_BUFFER_KEY_PRESS];
+ if(displayIc)
+ {
+ Status status;
+ char databuf[SIZE_BUFFER_KEY_PRESS];
+ nbReadBuf = Xutf8LookupString(displayIc, &event.xkey, databuf,
+ SIZE_BUFFER_KEY_PRESS, &keysym, &status);
+ if(nbReadBuf > 0) {
+ nbReadBuf = Util::utf8ToUtf16(databuf, nbReadBuf,
+ utf16buf, SIZE_BUFFER_KEY_PRESS);
+ }
+ }
+ else
+ {
XComposeStatus compstatus;
- int xx = 0;
- int yy = 0;
- string text;
- string formerString = "";
+ char databuf[SIZE_BUFFER_KEY_PRESS];
+ nbReadBuf = XLookupString(&event.xkey, databuf,
+ SIZE_BUFFER_KEY_PRESS, &keysym, &compstatus);
+ if(nbReadBuf > 0) {
+ nbReadBuf = Util::utf8ToUtf16(databuf, nbReadBuf,
+ utf16buf, SIZE_BUFFER_KEY_PRESS);
+ }
+ }
- XLookupString(&event.xkey, &ascii, 1, &keysym, &compstatus);
switch(keysym){
case XK_F1:
SwitchSession();
@@ -553,17 +641,17 @@
case XK_KP_Enter:
if (field==Get_Name){
/* Don't allow an empty username */
- if (NameBuffer.empty()) return true;
+ if (nameBufferLen <= 0) return true;
- if (NameBuffer==CONSOLE_STR){
+ if (Util::utf16EqualToAscii(CONSOLE_STR, nameBuffer, nameBufferLen)) {
action = Console;
- } else if (NameBuffer==HALT_STR){
+ } else if (Util::utf16EqualToAscii(HALT_STR, nameBuffer, nameBufferLen)) {
action = Halt;
- } else if (NameBuffer==REBOOT_STR){
+ } else if (Util::utf16EqualToAscii(REBOOT_STR, nameBuffer, nameBufferLen)) {
action = Reboot;
- } else if (NameBuffer==SUSPEND_STR){
+ } else if (Util::utf16EqualToAscii(SUSPEND_STR, nameBuffer, nameBufferLen)) {
action = Suspend;
- } else if (NameBuffer==EXIT_STR){
+ } else if (Util::utf16EqualToAscii(EXIT_STR, nameBuffer, nameBufferLen)) {
action = Exit;
} else{
if (mode == Mode_DM)
@@ -581,80 +669,80 @@
switch(keysym){
case XK_Delete:
case XK_BackSpace:
- EraseLastChar(formerString);
+ formerTextBufferLen = FieldEraseLastChar(&textBuffer, &textBufferLen);
break;
case XK_w:
case XK_u:
if (reinterpret_cast<XKeyEvent&>(event).state & ControlMask) {
- switch(field) {
- case Get_Passwd:
- formerString = HiddenPasswdBuffer;
- HiddenPasswdBuffer.clear();
- PasswdBuffer.clear();
- break;
- case Get_Name:
- formerString = NameBuffer;
- NameBuffer.clear();
- break;
- }
+ formerTextBufferLen = FieldClear(&textBuffer, &textBufferLen);
break;
}
case XK_h:
if (reinterpret_cast<XKeyEvent&>(event).state & ControlMask) {
- EraseLastChar(formerString);
+ formerTextBufferLen = FieldEraseLastChar(&textBuffer, &textBufferLen);
break;
}
/* Deliberate fall-through */
default:
- if (isprint(ascii) && (keysym < XK_Shift_L || keysym > XK_Hyper_R)){
+ if(nbReadBuf > 0) {
switch(field) {
- case GET_NAME:
- formerString=NameBuffer;
- if (NameBuffer.length() < INPUT_MAXLENGTH_NAME-1){
- NameBuffer.append(&ascii,1);
- };
+ case Get_Name:
+ formerTextBufferLen = nameBufferLen;
+ for(int i = 0; i < nbReadBuf &&
+ nameBufferLen < INPUT_MAXLENGTH_NAME; i++) {
+
+ if(isUtf16CharAllowed(utf16buf[i])) {
+ nameBuffer[nameBufferLen++] = utf16buf[i];
+ }
+ }
+ textBuffer = nameBuffer;
+ textBufferLen = nameBufferLen;
break;
- case GET_PASSWD:
- formerString=HiddenPasswdBuffer;
- if (PasswdBuffer.length() < INPUT_MAXLENGTH_PASSWD-1){
- PasswdBuffer.append(&ascii,1);
- HiddenPasswdBuffer.append("*");
- };
+
+ case Get_Passwd:
+ formerTextBufferLen = passwdBufferLen;
+ for(int i = 0; i < nbReadBuf &&
+ passwdBufferLen < INPUT_MAXLENGTH_PASSWD; i++) {
+
+ if(isUtf16CharAllowed(utf16buf[i])) {
+ passwdBuffer[passwdBufferLen] = utf16buf[i];
+ hiddenPasswdBuffer[passwdBufferLen++] = (uint16_t)'*';
+ }
+ }
+ textBuffer = hiddenPasswdBuffer;
+ textBufferLen = passwdBufferLen;
break;
- };
- };
+ }
+ }
break;
};
- XGlyphInfo extents;
- XftDraw *draw = XftDrawCreate(Dpy, Win,
- DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
+ int xx = 0, yy = 0;
+ if (formerTextBufferLen > 0 || textBufferLen > 0) {
switch(field) {
case Get_Name:
- text = NameBuffer;
xx = input_name_x;
yy = input_name_y;
break;
case Get_Passwd:
- text = HiddenPasswdBuffer;
xx = input_pass_x;
yy = input_pass_y;
break;
}
+ }
- if (!formerString.empty()){
+ if (formerTextBufferLen > 0) {
+ XGlyphInfo extents;
const char* txth = "Wj"; /* get proper maximum height ? */
XftTextExtents8(Dpy, font,
reinterpret_cast<const XftChar8*>(txth), strlen(txth), &extents);
int maxHeight = extents.height;
- XftTextExtents8(Dpy, font,
- reinterpret_cast<const XftChar8*>(formerString.c_str()),
- formerString.length(), &extents);
+ XftTextExtents16(Dpy, font, (XftChar16*)textBuffer, formerTextBufferLen, &extents);
int maxLength = extents.width;
if (mode == Mode_Lock)
@@ -666,14 +754,15 @@
maxLength + 6, maxHeight + 6, false);
}
- if (!text.empty()) {
- SlimDrawString8 (draw, &inputcolor, font, xx, yy,
- text,
- &inputshadowcolor,
- inputShadowXOffset, inputShadowYOffset);
+ if(textBufferLen > 0) {
+ XftDraw *draw = XftDrawCreate(Dpy, Win, DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
+ if(draw != NULL) {
+ SlimDrawString16(draw, &inputcolor, font, xx, yy, textBuffer, textBufferLen,
+ &inputshadowcolor, inputShadowXOffset, inputShadowYOffset);
+ XftDrawDestroy(draw);
+ }
}
- XftDrawDestroy (draw);
Cursor(SHOW);
return true;
}
@@ -690,7 +779,7 @@
XftDraw *draw = XftDrawCreate(Dpy, Win,
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
/* welcome message */
- XftTextExtents8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
+ XftTextExtentsUtf8(Dpy, welcomefont, (XftChar8*)welcome_message.c_str(),
strlen(welcome_message.c_str()), &extents);
cfgX = cfg->getOption("welcome_x");
cfgY = cfg->getOption("welcome_y");
@@ -700,9 +789,8 @@
welcome_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
welcome_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
if (welcome_x >= 0 && welcome_y >= 0) {
- SlimDrawString8 (draw, &welcomecolor, welcomefont,
- welcome_x, welcome_y,
- welcome_message,
+ SlimDrawStringUtf8(draw, &welcomecolor, welcomefont,
+ welcome_x, welcome_y, welcome_message,
&welcomeshadowcolor, shadowXOffset, shadowYOffset);
}
@@ -710,7 +798,7 @@
string msg;
if ((!singleInputMode|| field == Get_Passwd) && mode == Mode_DM) {
msg = cfg->getOption("password_msg");
- XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
+ XftTextExtentsUtf8(Dpy, enterfont, (XftChar8*)msg.c_str(),
strlen(msg.c_str()), &extents);
cfgX = cfg->getOption("password_x");
cfgY = cfg->getOption("password_y");
@@ -719,14 +807,14 @@
password_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
password_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
if (password_x >= 0 && password_y >= 0){
- SlimDrawString8 (draw, &entercolor, enterfont, password_x, password_y,
+ SlimDrawStringUtf8(draw, &entercolor, enterfont, password_x, password_y,
msg, &entershadowcolor, shadowXOffset, shadowYOffset);
}
}
if (!singleInputMode|| field == Get_Name) {
msg = cfg->getOption("username_msg");
- XftTextExtents8(Dpy, enterfont, (XftChar8*)msg.c_str(),
+ XftTextExtentsUtf8(Dpy, enterfont, (XftChar8*)msg.c_str(),
strlen(msg.c_str()), &extents);
cfgX = cfg->getOption("username_x");
cfgY = cfg->getOption("username_y");
@@ -735,7 +823,7 @@
username_x = Cfg::absolutepos(cfgX, image->Width(), extents.width);
username_y = Cfg::absolutepos(cfgY, image->Height(), extents.height);
if (username_x >= 0 && username_y >= 0){
- SlimDrawString8 (draw, &entercolor, enterfont, username_x, username_y,
+ SlimDrawStringUtf8(draw, &entercolor, enterfont, username_x, username_y,
msg, &entershadowcolor, shadowXOffset, shadowYOffset);
}
}
@@ -776,7 +864,7 @@
XftDraw *draw = XftDrawCreate(Dpy, Root,
DefaultVisual(Dpy, Scr), DefaultColormap(Dpy, Scr));
- XftTextExtents8(Dpy, sessionfont, reinterpret_cast<const XftChar8*>(currsession.c_str()),
+ XftTextExtentsUtf8(Dpy, sessionfont, reinterpret_cast<const XftChar8*>(currsession.c_str()),
currsession.length(), &extents);
msg_x = cfg->getOption("session_x");
msg_y = cfg->getOption("session_y");
@@ -785,16 +873,37 @@
int shadowXOffset = cfg->getIntOption("session_shadow_xoffset");
int shadowYOffset = cfg->getIntOption("session_shadow_yoffset");
- SlimDrawString8(draw, &sessioncolor, sessionfont, x, y,
- currsession,
- &sessionshadowcolor,
- shadowXOffset, shadowYOffset);
+ SlimDrawStringUtf8(draw, &sessioncolor, sessionfont, x, y,
+ currsession, &sessionshadowcolor, shadowXOffset, shadowYOffset);
XFlush(Dpy);
XftDrawDestroy(draw);
}
+void Panel::SlimDrawString16(XftDraw *d, XftColor *color, XftFont *font,
+ int x, int y, const uint16_t *str, int strLen,
+ XftColor* shadowColor, int xOffset, int yOffset)
+{
+ int calc_x = 0;
+ int calc_y = 0;
+ if (mode == Mode_Lock) {
+ calc_x = viewport.x;
+ calc_y = viewport.y;
+ }
+
+ if (xOffset && yOffset) {
+ XftDrawString16(d, shadowColor, font,
+ x + xOffset + calc_x,
+ y + yOffset + calc_y,
+ (XftChar16*)str, strLen);
+ }
+
+ XftDrawString16(d, color, font,
+ x + calc_x,
+ y + calc_y,
+ (XftChar16*)str, strLen);
+}
-void Panel::SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
+void Panel::SlimDrawStringUtf8(XftDraw *d, XftColor *color, XftFont *font,
int x, int y, const string& str,
XftColor* shadowColor,
int xOffset, int yOffset)
@@ -831,28 +940,31 @@
}
void Panel::ResetName(void){
- NameBuffer.clear();
+ nameBufferLen = 0;
+ memset(nameBuffer, 0, sizeof(nameBuffer));
}
void Panel::ResetPasswd(void){
- PasswdBuffer.clear();
- HiddenPasswdBuffer.clear();
+ passwdBufferLen = 0;
+ memset(passwdBuffer, 0, sizeof(passwdBuffer));
+ memset(hiddenPasswdBuffer, 0, sizeof(hiddenPasswdBuffer));
}
void Panel::SetName(const string& name){
- NameBuffer=name;
+ nameBufferLen = Util::utf8ToUtf16(name.c_str(), name.length(),
+ nameBuffer, INPUT_MAXLENGTH_NAME);
if (mode == Mode_DM)
action = Login;
else
action = Lock;
}
-const string& Panel::GetName(void) const{
- return NameBuffer;
+const string Panel::GetName(void) const{
+ return Util::utf16BufToUtf8String(nameBuffer, nameBufferLen);
}
-const string& Panel::GetPasswd(void) const{
- return PasswdBuffer;
+const string Panel::GetPasswd(void) const{
+ return Util::utf16BufToUtf8String(passwdBuffer, passwdBufferLen);
}
Rectangle Panel::GetPrimaryViewport() {
--- panel.h.orig 2014-08-12 18:08:28.000000000 +0200
+++ panel.h 2014-08-12 18:09:20.000000000 +0200
@@ -20,6 +20,7 @@
#include <X11/Xmu/WinUtil.h>
#include <sys/wait.h>
#include <stdlib.h>
+#include <stdint.h>
#include <signal.h>
#include <iostream>
#include <string>
@@ -86,20 +87,26 @@
void ResetName(void);
void ResetPasswd(void);
void SetName(const std::string &name);
- const std::string& GetName(void) const;
- const std::string& GetPasswd(void) const;
+ const std::string GetName(void) const;
+ const std::string GetPasswd(void) const;
void SwitchSession();
private:
Panel();
void Cursor(int visible);
unsigned long GetColor(const char *colorname);
void OnExpose(void);
- void EraseLastChar(string &formerString);
+ int FieldEraseLastChar(const uint16_t **buf, int *len);
+ int FieldClear(const uint16_t **buf, int *len);
bool OnKeyPress(XEvent& event);
void ShowText();
void ShowSession();
- void SlimDrawString8(XftDraw *d, XftColor *color, XftFont *font,
+ static bool isUtf16CharAllowed(uint16_t c);
+ void SlimDrawString16(XftDraw *d, XftColor *color, XftFont *font,
+ int x, int y, const uint16_t *str, int strLen,
+ XftColor* shadowColor, int xOffset, int yOffset);
+
+ void SlimDrawStringUtf8(XftDraw *d, XftColor *color, XftFont *font,
int x, int y, const std::string &str,
XftColor *shadowColor,
int xOffset, int yOffset);
@@ -136,12 +143,16 @@
XftColor entershadowcolor;
ActionType action;
FieldType field;
+ XIM displayIm;
+ XIC displayIc;
//Pixmap background;
/* Username/Password */
- std::string NameBuffer;
- std::string PasswdBuffer;
- std::string HiddenPasswdBuffer;
+ uint16_t nameBuffer[INPUT_MAXLENGTH_NAME + 1];
+ int nameBufferLen;
+ uint16_t passwdBuffer[INPUT_MAXLENGTH_PASSWD + 1];
+ int passwdBufferLen;
+ uint16_t hiddenPasswdBuffer[INPUT_MAXLENGTH_PASSWD + 1];
/* screen stuff */
Rectangle viewport;
--- slimlock.cpp.orig 2014-08-12 18:08:28.000000000 +0200
+++ slimlock.cpp 2014-08-12 18:09:24.000000000 +0200
@@ -48,19 +48,19 @@
void *RaiseWindow(void *data);
// I really didn't wanna put these globals here, but it's the only way...
-Display* dpy;
-int scr;
-Window win;
-Cfg* cfg;
-Panel* loginPanel;
-string themeName = "";
-
-pam_handle_t *pam_handle;
-struct pam_conv conv = {ConvCallback, NULL};
-
-CARD16 dpms_standby, dpms_suspend, dpms_off, dpms_level;
-BOOL dpms_state, using_dpms;
-int term;
+static Display* dpy;
+static int scr;
+static Window win;
+static Cfg* cfg;
+static Panel* loginPanel;
+static string themeName = "";
+
+static pam_handle_t *pam_handle;
+static struct pam_conv conv = {ConvCallback, NULL};
+
+static CARD16 dpms_standby, dpms_suspend, dpms_off, dpms_level;
+static BOOL dpms_state, using_dpms;
+static int term;
static void
die(const char *errstr, ...) {
@@ -73,6 +73,10 @@
}
int main(int argc, char **argv) {
+
+ // We need to set the locale to get the input encoded in UTF-8
+ setlocale (LC_ALL, "");
+
if((argc == 2) && !strcmp("-v", argv[1]))
die(APPNAME"-"VERSION", © 2010-2012 Joel Burget\n");
else if(argc != 1)
--- switchuser.h.orig 2014-08-12 18:08:28.000000000 +0200
+++ switchuser.h 2014-08-12 18:09:20.000000000 +0200
@@ -32,8 +32,6 @@
void Login(const char* cmd, const char* mcookie);
private:
- SwitchUser();
- void SetEnvironment();
void SetUserId();
void Execute(const char* cmd);
void SetClientAuth(const char* mcookie);
--- util.cpp.orig 2014-08-12 18:08:28.000000000 +0200
+++ util.cpp 2014-08-12 18:09:20.000000000 +0200
@@ -67,3 +67,162 @@
return pid + tm + (ts.tv_sec ^ ts.tv_nsec);
}
+
+/* Given a UTF-8 encoded string pointed to by utf8 of length length in
+bytes, returns the corresponding UTF-16 encoded string in the
+buffer pointed to by utf16. The maximum number of UTF-16 encoding
+units (i.e., Unit16s) allowed in the buffer is specified in
+utf16_max_length. The return value is the number of UTF-16
+encoding units placed in the output buffer pointed to by utf16.
+
+In case of an error, -1 is returned, leaving some unusable partial
+results in the output buffer.
+
+The caller must estimate the size of utf16 buffer by itself before
+calling this function. Insufficient output buffer is considered as
+an error, and once an error occured, this function doesn't give any
+clue how large the result will be.
+
+The error cases include following:
+
+- Invalid byte sequences were in the input UTF-8 bytes. The caller
+ has no way to know what point in the input buffer was the
+ errornous byte.
+
+- The input contained a character (a valid UTF-8 byte sequence)
+ whose scalar value exceeded the range that UTF-16 can represent
+ (i.e., characters whose Unicode scalar value above 0x110000).
+
+- The output buffer has no enough space to hold entire utf16 data.
+
+Please note:
+
+- '\0'-termination is not assumed both on the input UTF-8 string
+ and on the output UTF-16 string; any legal zero byte in the input
+ UTF-8 string will be converted to a 16-bit zero in output. As a
+ side effect, the last UTF-16 encoding unit stored in the output
+ buffer will have a non-zero value if the input UTF-8 was not
+ '\0'-terminated.
+
+- UTF-8 aliases are *not* considered as an error. They are
+ converted to UTF-16. For example, 0xC0 0xA0, 0xE0 0x80 0xA0,
+ and 0xF0 0x80 0x80 0xA0 are all mapped to a single UTF-16
+ encoding unit 0x0020.
+
+- Three byte UTF-8 sequences whose value corresponds to a surrogate
+ code or other reserved scalar value are not considered as an
+ error either. They may cause an invalid UTF-16 data (e.g., those
+ containing unpaired surrogates).
+
+*/
+int Util::utf8ToUtf16(const char *buf, const int utf8_length, uint16_t *utf16, const int utf16_max_length) {
+
+ /* p moves over the output buffer. max_ptr points to the next to the last slot of the buffer. */
+ uint16_t *p = utf16;
+ const uint16_t *max_ptr = utf16 + utf16_max_length;
+ const unsigned char *utf8 = (const unsigned char *)buf;
+
+ /* end_of_input points to the last byte of input as opposed to the next to the last byte. */
+ unsigned char const *const end_of_input = utf8 + utf8_length - 1;
+
+ while (utf8 <= end_of_input) {
+ const unsigned char c = *utf8;
+ if (p >= max_ptr) {
+ /* No more output space. */
+ return -1;
+ }
+ if (c < 0x80) {
+ /* One byte ASCII. */
+ *p++ = c;
+ utf8 += 1;
+ } else if (c < 0xC0) {
+ /* Follower byte without preceeding leader bytes. */
+ return -1;
+ } else if (c < 0xE0) {
+ /* Two byte sequence. We need one follower byte. */
+ if (end_of_input - utf8 < 1 || (((utf8[1] ^ 0x80)) & 0xC0)) {
+ return -1;
+ }
+ *p++ = (uint16_t)(0xCF80 + (c << 6) + utf8[1]);
+ utf8 += 2;
+ } else if (c < 0xF0) {
+ /* Three byte sequence. We need two follower byte. */
+ if (end_of_input - utf8 < 2 || (((utf8[1] ^ 0x80) | (utf8[2] ^ 0x80)) & 0xC0)) {
+ return -1;
+ }
+ *p++ = (uint16_t)(0xDF80 + (c << 12) + (utf8[1] << 6) + utf8[2]);
+ utf8 += 3;
+ } else if (c < 0xF8) {
+ int plane;
+ /* Four byte sequence. We need three follower bytes. */
+ if (end_of_input - utf8 < 3 || (((utf8[1] ^ 0x80) | (utf8[2] ^0x80) | (utf8[3] ^ 0x80)) & 0xC0)) {
+ return -1;
+ }
+ plane = (-0xC8 + (c << 2) + (utf8[1] >> 4));
+ if (plane == 0) {
+ /* This four byte sequence is an alias that
+ corresponds to a Unicode scalar value in BMP.
+ It fits in an UTF-16 encoding unit. */
+ *p++ = (uint16_t)(0xDF80 + (utf8[1] << 12) + (utf8[2] << 6) + utf8[3]);
+ } else if (plane <= 16) {
+ /* This is a legal four byte sequence that corresponds to a surrogate pair. */
+ if (p + 1 >= max_ptr) {
+ /* No enough space on the output buffer for the pair. */
+ return -1;
+ }
+ *p++ = (uint16_t)(0xE5B8 + (c << 8) + (utf8[1] << 2) + (utf8[2] >> 4));
+ *p++ = (uint16_t)(0xDB80 + ((utf8[2] & 0x0F) << 6) + utf8[3]);
+ } else {
+ /* This four byte sequence is out of UTF-16 code space. */
+ return -1;
+ }
+ utf8 += 4;
+ } else {
+ /* Longer sequence or unused byte. */
+ return -1;
+ }
+ }
+ return p - utf16;
+}
+
+/* Compare an ASCII string with an UTF-16 string */
+bool Util::utf16EqualToAscii(const char *ascii, uint16_t *utf16, int utf16Len) {
+
+ while(*ascii != 0 && utf16Len > 0) {
+ if(*utf16++ != (uint16_t)*ascii++) {
+ return false;
+ }
+ utf16Len--;
+ }
+ return *ascii == 0 && utf16Len == 0;
+}
+
+std::string Util::utf16BufToUtf8String(const uint16_t *utf16Buf, int utf16Len) {
+
+ std::string outStr;
+ outStr.reserve(utf16Len * 2);
+
+ while(*utf16Buf != 0 && utf16Len > 0) {
+
+ const uint16_t c16 = *utf16Buf++;
+ if (c16 <= 0x007F) {
+ outStr.push_back((char)c16);
+ }
+ else if (c16 <= 0x07FF) {
+ unsigned char c = 0xC0 | ((unsigned char)(c16 >> 6));
+ outStr.push_back(c);
+ c = 0x80 | ((unsigned char)(c16 & 0x003F));
+ outStr.push_back(c);
+ }
+ else {
+ unsigned char c = 0xE0 | ((unsigned char)(c16 >> 12));
+ outStr.push_back(c);
+ c = 0x80 | ((unsigned char)((c16 >> 6) & 0x003F));
+ outStr.push_back(c);
+ c = 0x80 | ((unsigned char)(c16 & 0x003F));
+ outStr.push_back(c);
+ }
+ utf16Len--;
+ }
+ return outStr;
+}
--- util.h.orig 2014-08-12 18:08:28.000000000 +0200
+++ util.h 2014-08-12 18:09:20.000000000 +0200
@@ -10,6 +10,7 @@
#define _UTIL_H__
#include <string>
+#include <stdint.h>
namespace Util {
bool add_mcookie(const std::string &mcookie, const char *display,
@@ -19,6 +20,10 @@
long random(void);
long makeseed(void);
+ int utf8ToUtf16(const char *utf8, const int utf8_length,
+ uint16_t *utf16, const int utf16_max_length);
+ bool utf16EqualToAscii(const char *ascii, uint16_t *utf16, int utf16Len);
+ std::string utf16BufToUtf8String(const uint16_t *utf16Buf, int utf16Len);
}
#endif /* _UTIL_H__ */