1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-30 02:12:30 +01:00

Applied patches from Stanislav Maslovski <stanislav.maslovski@gmail.com> to

fix the 2 problems mentioend below:

- Fixed buggy handling of UTF8 characters in textfields in WINGs.
- Fixed segfault in WPrefs when some font description is missing from the
  configuration file.
This commit is contained in:
dan
2006-04-25 23:52:43 +00:00
parent 4688c9839b
commit bc4de88d8b
3 changed files with 120 additions and 72 deletions

View File

@@ -33,6 +33,10 @@ Changes since version 0.92.0:
- Improved Info panel layout and fonts. - Improved Info panel layout and fonts.
- Fixed missing library paths when linking some binaries on certain - Fixed missing library paths when linking some binaries on certain
platforms with a recent pkg-config (debian unstable/sid for one) platforms with a recent pkg-config (debian unstable/sid for one)
- Fixed buggy handling of UTF8 characters in textfields in WINGs.
(Stanislav Maslovski <stanislav.maslovski@gmail.com>)
- Fixed segfault in WPrefs when some font description is missing from the
configuration file (Stanislav Maslovski <stanislav.maslovski@gmail.com>)
Changes since version 0.91.0: Changes since version 0.91.0:

View File

@@ -30,15 +30,15 @@ typedef struct W_TextField {
#endif #endif
char *text; char *text;
int textLen; /* size of text */ int textLen; /* size of text */
int bufferSize; /* memory allocated for text */ int bufferSize; /* memory allocated for text */
int viewPosition; /* position of text being shown */ int viewPosition; /* position of text being shown */
int cursorPosition; /* position of the insertion cursor */ int cursorPosition; /* position of the insertion cursor */
short usableWidth; short usableWidth;
short offsetWidth; /* offset of text from border */ short offsetWidth; /* offset of text from border */
WMRange selection; WMRange selection;
@@ -47,7 +47,7 @@ typedef struct W_TextField {
WMTextFieldDelegate *delegate; WMTextFieldDelegate *delegate;
#if 0 #if 0
WMHandlerID timerID; /* for cursor blinking */ WMHandlerID timerID; /* for cursor blinking */
#endif #endif
struct { struct {
WMAlignment alignment:2; WMAlignment alignment:2;
@@ -62,7 +62,7 @@ typedef struct W_TextField {
unsigned int cursorOn:1; unsigned int cursorOn:1;
unsigned int secure:1; /* password entry style */ unsigned int secure:1; /* password entry style */
unsigned int pointerGrabbed:1; unsigned int pointerGrabbed:1;
@@ -77,7 +77,7 @@ typedef struct W_TextField {
} TextField; } TextField;
#define NOTIFY(T,C,N,A) { WMNotification *notif = WMCreateNotification(N,T,A);\ #define NOTIFY(T,C,N,A) { WMNotification *notif = WMCreateNotification(N,T,A);\
if ((T)->delegate && (T)->delegate->C)\ if ((T)->delegate && (T)->delegate->C)\
(*(T)->delegate->C)((T)->delegate,notif);\ (*(T)->delegate->C)((T)->delegate,notif);\
WMPostNotification(notif);\ WMPostNotification(notif);\
@@ -136,11 +136,45 @@ static WMSelectionProcs selectionHandler = {
}; };
#define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->font, \ #define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->font, \
&((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1)) &((tPtr)->text[(start)]), (tPtr)->textLen - (start)))
#define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->font, \ #define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->font, \
&((tPtr)->text[(start)]), (end) - (start) + 1)) &((tPtr)->text[(start)]), (end) - (start)))
static INLINE int
oneUTF8CharBackward(char *str, int len)
{
unsigned char* ustr = (unsigned char*) str;
int pos = 0;
while (len-- > 0 && ustr[--pos] >= 0x80 && ustr[pos] <= 0xbf);
return pos;
}
static INLINE int
oneUTF8CharForward(char *str, int len)
{
unsigned char* ustr = (unsigned char*) str;
int pos = 0;
while (len-- > 0 && ustr[++pos] >= 0x80 && ustr[pos] <= 0xbf);
return pos;
}
// find the beginning of the UTF8 char pointed by str
static INLINE int
seekUTF8CharStart(char *str, int len)
{
unsigned char* ustr = (unsigned char*) str;
int pos = 0;
while (len-- > 0 && ustr[pos] >= 0x80 && ustr[pos] <= 0xbf) --pos;
return pos;
}
static void static void
@@ -177,6 +211,7 @@ normalizeRange(TextField *tPtr, WMRange *range)
range->count = tPtr->textLen - range->position; range->count = tPtr->textLen - range->position;
} }
static void static void
memmv(char *dest, char *src, int size) memmv(char *dest, char *src, int size)
{ {
@@ -200,7 +235,8 @@ incrToFit(TextField *tPtr)
int vp = tPtr->viewPosition; int vp = tPtr->viewPosition;
while (TEXT_WIDTH(tPtr, tPtr->viewPosition) > tPtr->usableWidth) { while (TEXT_WIDTH(tPtr, tPtr->viewPosition) > tPtr->usableWidth) {
tPtr->viewPosition++; tPtr->viewPosition += oneUTF8CharForward(&tPtr->text[tPtr->viewPosition],
tPtr->textLen - tPtr->viewPosition);
} }
return vp!=tPtr->viewPosition; return vp!=tPtr->viewPosition;
} }
@@ -210,11 +246,11 @@ static int
incrToFit2(TextField *tPtr) incrToFit2(TextField *tPtr)
{ {
int vp = tPtr->viewPosition; int vp = tPtr->viewPosition;
while (TEXT_WIDTH2(tPtr, tPtr->viewPosition, tPtr->cursorPosition) while (TEXT_WIDTH2(tPtr, tPtr->viewPosition, tPtr->cursorPosition)
>= tPtr->usableWidth) >= tPtr->usableWidth)
tPtr->viewPosition++; tPtr->viewPosition += oneUTF8CharForward(&tPtr->text[tPtr->viewPosition],
tPtr->cursorPosition - tPtr->viewPosition);
return vp!=tPtr->viewPosition; return vp!=tPtr->viewPosition;
} }
@@ -222,16 +258,18 @@ incrToFit2(TextField *tPtr)
static void static void
decrToFit(TextField *tPtr) decrToFit(TextField *tPtr)
{ {
while (TEXT_WIDTH(tPtr, tPtr->viewPosition-1) < tPtr->usableWidth int vp = tPtr->viewPosition;
&& tPtr->viewPosition>0)
tPtr->viewPosition--; while (vp > 0 && (vp += oneUTF8CharBackward(&tPtr->text[vp], vp),
TEXT_WIDTH(tPtr, vp)) < tPtr->usableWidth) {
tPtr->viewPosition = vp;
}
} }
#undef TEXT_WIDTH #undef TEXT_WIDTH
#undef TEXT_WIDTH2 #undef TEXT_WIDTH2
static WMData* static WMData*
requestHandler(WMView *view, Atom selection, Atom target, void *cdata, requestHandler(WMView *view, Atom selection, Atom target, void *cdata,
Atom *type) Atom *type)
@@ -419,11 +457,9 @@ WMInsertTextFieldText(WMTextField *tPtr, char *text, int position)
if (position < 0 || position >= tPtr->textLen) { if (position < 0 || position >= tPtr->textLen) {
/* append the text at the end */ /* append the text at the end */
strcat(tPtr->text, text); strcat(tPtr->text, text);
incrToFit(tPtr);
tPtr->textLen += len; tPtr->textLen += len;
tPtr->cursorPosition += len; tPtr->cursorPosition += len;
incrToFit(tPtr);
} else { } else {
/* insert text at position */ /* insert text at position */
memmv(&(tPtr->text[position+len]), &(tPtr->text[position]), memmv(&(tPtr->text[position+len]), &(tPtr->text[position]),
@@ -456,12 +492,11 @@ WMDeleteTextFieldRange(WMTextField *tPtr, WMRange range)
memmv(&(tPtr->text[range.position]), &(tPtr->text[range.position+range.count]), memmv(&(tPtr->text[range.position]), &(tPtr->text[range.position+range.count]),
tPtr->textLen - (range.position+range.count) + 1); tPtr->textLen - (range.position+range.count) + 1);
/* better than nothing ;) */
if (tPtr->cursorPosition > range.position)
tPtr->viewPosition += oneUTF8CharBackward(&tPtr->text[tPtr->viewPosition],
tPtr->viewPosition);
tPtr->textLen -= range.count; tPtr->textLen -= range.count;
/* try to keep cursorPosition at the same place */
tPtr->viewPosition -= range.count;
if (tPtr->viewPosition < 0)
tPtr->viewPosition = 0;
tPtr->cursorPosition = range.position; tPtr->cursorPosition = range.position;
decrToFit(tPtr); decrToFit(tPtr);
@@ -1096,16 +1131,18 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
#endif #endif
case XK_Left: case XK_Left:
if (tPtr->cursorPosition > 0) { if (tPtr->cursorPosition > 0) {
int i;
paintCursor(tPtr); paintCursor(tPtr);
if (controled) {
int i = tPtr->cursorPosition - 1;
i = tPtr->cursorPosition;
i += oneUTF8CharBackward(&tPtr->text[i], i);
if (controled) {
while (i > 0 && tPtr->text[i] != ' ') i--; while (i > 0 && tPtr->text[i] != ' ') i--;
while (i > 0 && tPtr->text[i] == ' ') i--; while (i > 0 && tPtr->text[i] == ' ') i--;
tPtr->cursorPosition = (i > 0) ? i + 1 : 0; tPtr->cursorPosition = (i > 0) ? i + 1 : 0;
} else } else
tPtr->cursorPosition--; tPtr->cursorPosition = i;
if (tPtr->cursorPosition < tPtr->viewPosition) { if (tPtr->cursorPosition < tPtr->viewPosition) {
tPtr->viewPosition = tPtr->cursorPosition; tPtr->viewPosition = tPtr->cursorPosition;
@@ -1131,24 +1168,20 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
#endif #endif
case XK_Right: case XK_Right:
if (tPtr->cursorPosition < tPtr->textLen) { if (tPtr->cursorPosition < tPtr->textLen) {
int i;
paintCursor(tPtr); paintCursor(tPtr);
if (controled) {
int i = tPtr->cursorPosition;
i = tPtr->cursorPosition;
if (controled) {
while (tPtr->text[i] && tPtr->text[i] != ' ') i++; while (tPtr->text[i] && tPtr->text[i] != ' ') i++;
while (tPtr->text[i] == ' ') i++; while (tPtr->text[i] == ' ') i++;
tPtr->cursorPosition = i;
} else { } else {
tPtr->cursorPosition++; i += oneUTF8CharForward(&tPtr->text[i], tPtr->textLen - i);
}
while (WMWidthOfString(tPtr->font,
&(tPtr->text[tPtr->viewPosition]),
tPtr->cursorPosition-tPtr->viewPosition)
> tPtr->usableWidth) {
tPtr->viewPosition++;
refresh = 1;
} }
tPtr->cursorPosition = i;
refresh = incrToFit2(tPtr);
if (!refresh) if (!refresh)
paintCursor(tPtr); paintCursor(tPtr);
} }
@@ -1201,13 +1234,9 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
paintCursor(tPtr); paintCursor(tPtr);
tPtr->cursorPosition = tPtr->textLen; tPtr->cursorPosition = tPtr->textLen;
tPtr->viewPosition = 0; tPtr->viewPosition = 0;
while (WMWidthOfString(tPtr->font,
&(tPtr->text[tPtr->viewPosition]), refresh = incrToFit(tPtr);
tPtr->textLen-tPtr->viewPosition)
> tPtr->usableWidth) {
tPtr->viewPosition++;
refresh = 1;
}
if (!refresh) if (!refresh)
paintCursor(tPtr); paintCursor(tPtr);
} }
@@ -1231,9 +1260,11 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
data = (void*)WMDeleteTextEvent; data = (void*)WMDeleteTextEvent;
textEvent = WMTextDidChangeNotification; textEvent = WMTextDidChangeNotification;
} else if (tPtr->cursorPosition > 0) { } else if (tPtr->cursorPosition > 0) {
int i = oneUTF8CharBackward(&tPtr->text[tPtr->cursorPosition],
tPtr->cursorPosition);
WMRange range; WMRange range;
range.position = tPtr->cursorPosition - 1; range.position = tPtr->cursorPosition + i;
range.count = 1; range.count = -i;
WMDeleteTextFieldRange(tPtr, range); WMDeleteTextFieldRange(tPtr, range);
data = (void*)WMDeleteTextEvent; data = (void*)WMDeleteTextEvent;
textEvent = WMTextDidChangeNotification; textEvent = WMTextDidChangeNotification;
@@ -1261,7 +1292,8 @@ handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
} else if (tPtr->cursorPosition < tPtr->textLen) { } else if (tPtr->cursorPosition < tPtr->textLen) {
WMRange range; WMRange range;
range.position = tPtr->cursorPosition; range.position = tPtr->cursorPosition;
range.count = 1; range.count = oneUTF8CharForward(&tPtr->text[tPtr->cursorPosition],
tPtr->textLen - tPtr->cursorPosition);
WMDeleteTextFieldRange(tPtr, range); WMDeleteTextFieldRange(tPtr, range);
data = (void*)WMDeleteTextEvent; data = (void*)WMDeleteTextEvent;
textEvent = WMTextDidChangeNotification; textEvent = WMTextDidChangeNotification;
@@ -1356,23 +1388,26 @@ pointToCursorPosition(TextField *tPtr, int x)
a = tPtr->viewPosition; a = tPtr->viewPosition;
b = tPtr->textLen; b = tPtr->textLen;
while (a < b && b-a>1) { while (a < b) {
mid = (a+b)/2; mid = (a+b)/2;
mid += seekUTF8CharStart(&tPtr->text[mid], mid - a);
tw = WMWidthOfString(tPtr->font, &(tPtr->text[tPtr->viewPosition]), tw = WMWidthOfString(tPtr->font, &(tPtr->text[tPtr->viewPosition]),
mid - tPtr->viewPosition); mid - tPtr->viewPosition + 1);
if (tw > x) if (tw > x) {
b = mid; b = mid;
else if (tw < x) } else if (tw < x) {
a = mid; if (a == mid)
else a += oneUTF8CharForward(&tPtr->text[mid], b - a);
else
a = mid;
} else {
return mid; return mid;
}
} }
return b;
return (a+b)/2;
} }
static void static void
pasteText(WMView *view, Atom selection, Atom target, Time timestamp, pasteText(WMView *view, Atom selection, Atom target, Time timestamp,
void *cdata, WMData *data) void *cdata, WMData *data)
@@ -1447,11 +1482,13 @@ handleTextFieldActionEvents(XEvent *event, void *data)
&(tPtr->text[tPtr->viewPosition]), &(tPtr->text[tPtr->viewPosition]),
tPtr->cursorPosition-tPtr->viewPosition) tPtr->cursorPosition-tPtr->viewPosition)
> tPtr->usableWidth) { > tPtr->usableWidth) {
tPtr->viewPosition++; tPtr->viewPosition += oneUTF8CharForward(&tPtr->text[tPtr->viewPosition],
tPtr->textLen - tPtr->viewPosition);
} }
} else if (tPtr->viewPosition > 0 && event->xmotion.x < 0) { } else if (tPtr->viewPosition > 0 && event->xmotion.x < 0) {
paintCursor(tPtr); paintCursor(tPtr);
tPtr->viewPosition--; tPtr->viewPosition += oneUTF8CharBackward(&tPtr->text[tPtr->viewPosition],
tPtr->viewPosition);
} }
tPtr->cursorPosition = tPtr->cursorPosition =

View File

@@ -312,9 +312,14 @@ static char*
getSelectedFont(_Panel *panel, FcChar8 *curfont) getSelectedFont(_Panel *panel, FcChar8 *curfont)
{ {
WMListItem *item; WMListItem *item;
FcPattern *pat= FcNameParse(curfont); FcPattern *pat;
char *name; char *name;
if (curfont)
pat= FcNameParse(curfont);
else
pat= FcPatternCreate();
item= WMGetListSelectedItem(panel->familyL); item= WMGetListSelectedItem(panel->familyL);
if (item) if (item)
{ {
@@ -358,12 +363,13 @@ updateSampleFont(_Panel *panel)
WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP, WMMenuItem *item= WMGetPopUpButtonMenuItem(panel->optionP,
WMGetPopUpButtonSelectedItem(panel->optionP)); WMGetPopUpButtonSelectedItem(panel->optionP));
char *fn= WMGetMenuItemRepresentedObject(item); char *fn= WMGetMenuItemRepresentedObject(item);
WMFont *font= WMCreateFont(WMWidgetScreen(panel->box), fn);
if (font) if (fn) {
{ WMFont *font= WMCreateFont(WMWidgetScreen(panel->box), fn);
WMSetTextFieldFont(panel->sampleT, font); if (font) {
WMReleaseFont(font); WMSetTextFieldFont(panel->sampleT, font);
WMReleaseFont(font);
}
} }
} }
@@ -451,8 +457,8 @@ selectedFamily(WMWidget *w, void *data)
ofont= (FcChar8*)WMGetMenuItemRepresentedObject(item); ofont= (FcChar8*)WMGetMenuItemRepresentedObject(item);
nfont= getSelectedFont(panel, ofont); nfont= getSelectedFont(panel, ofont);
wfree(ofont); if (ofont)
wfree(ofont);
WMSetMenuItemRepresentedObject(item, nfont); WMSetMenuItemRepresentedObject(item, nfont);
} }
updateSampleFont(panel); updateSampleFont(panel);
@@ -471,7 +477,8 @@ selected(WMWidget *w, void *data)
ofont = (FcChar8*)WMGetMenuItemRepresentedObject(item); ofont = (FcChar8*)WMGetMenuItemRepresentedObject(item);
nfont= getSelectedFont(panel, ofont); nfont= getSelectedFont(panel, ofont);
wfree(ofont); if (ofont)
wfree(ofont);
WMSetMenuItemRepresentedObject(item, nfont); WMSetMenuItemRepresentedObject(item, nfont);