This update includes the 0.20.3pre3 code
[wmaker-crm.git] / WINGs / wtextfield.c
blob5ececb23de76b43098e11fac093cfb42dc2f9b5f
5 #include "WINGsP.h"
7 #include <X11/keysym.h>
8 #include <X11/Xatom.h>
10 #include <ctype.h>
12 #define CURSOR_BLINK_ON_DELAY 600
13 #define CURSOR_BLINK_OFF_DELAY 300
16 char *WMTextDidChangeNotification = "WMTextDidChangeNotification";
17 char *WMTextDidBeginEditingNotification = "WMTextDidBeginEditingNotification";
18 char *WMTextDidEndEditingNotification = "WMTextDidEndEditingNotification";
21 typedef struct W_TextField {
22 W_Class widgetClass;
23 W_View *view;
25 struct W_TextField *nextField; /* next textfield in the chain */
26 struct W_TextField *prevField;
28 char *text;
29 int textLen; /* size of text */
30 int bufferSize; /* memory allocated for text */
32 int viewPosition; /* position of text being shown */
34 int cursorPosition; /* position of the insertion cursor */
36 short usableWidth;
37 short offsetWidth; /* offset of text from border */
39 #if 0
40 WMHandlerID timerID; /* for cursor blinking */
41 #endif
42 struct {
43 WMAlignment alignment:2;
45 unsigned int bordered:1;
47 unsigned int enabled:1;
49 unsigned int focused:1;
51 unsigned int cursorOn:1;
53 unsigned int secure:1; /* password entry style */
55 /**/
56 unsigned int notIllegalMovement:1;
57 } flags;
58 } TextField;
61 #define MIN_TEXT_BUFFER 2
62 #define TEXT_BUFFER_INCR 8
65 #define WM_EMACSKEYMASK ControlMask
67 #define WM_EMACSKEY_LEFT XK_b
68 #define WM_EMACSKEY_RIGHT XK_f
69 #define WM_EMACSKEY_HOME XK_a
70 #define WM_EMACSKEY_END XK_e
71 #define WM_EMACSKEY_BS XK_h
72 #define WM_EMACSKEY_DEL XK_d
76 #define DEFAULT_WIDTH 60
77 #define DEFAULT_HEIGHT 20
78 #define DEFAULT_BORDERED True
79 #define DEFAULT_ALIGNMENT WALeft
83 static void destroyTextField(TextField *tPtr);
84 static void paintTextField(TextField *tPtr);
86 static void handleEvents(XEvent *event, void *data);
87 static void handleTextFieldActionEvents(XEvent *event, void *data);
88 static void resizeTextField();
90 struct W_ViewProcedureTable _TextFieldViewProcedures = {
91 NULL,
92 resizeTextField,
93 NULL
97 #define TEXT_WIDTH(tPtr, start) (WMWidthOfString((tPtr)->view->screen->normalFont, \
98 &((tPtr)->text[(start)]), (tPtr)->textLen - (start) + 1))
100 #define TEXT_WIDTH2(tPtr, start, end) (WMWidthOfString((tPtr)->view->screen->normalFont, \
101 &((tPtr)->text[(start)]), (end) - (start) + 1))
104 static void
105 memmv(char *dest, char *src, int size)
107 int i;
109 if (dest > src) {
110 for (i=size-1; i>=0; i--) {
111 dest[i] = src[i];
113 } else if (dest < src) {
114 for (i=0; i<size; i++) {
115 dest[i] = src[i];
121 static int
122 incrToFit(TextField *tPtr)
124 int vp = tPtr->viewPosition;
126 while (TEXT_WIDTH(tPtr, tPtr->viewPosition) > tPtr->usableWidth) {
127 tPtr->viewPosition++;
129 return vp!=tPtr->viewPosition;
132 static int
133 incrToFit2(TextField *tPtr)
135 int vp = tPtr->viewPosition;
136 while (TEXT_WIDTH2(tPtr, tPtr->viewPosition, tPtr->cursorPosition)
137 >= tPtr->usableWidth)
138 tPtr->viewPosition++;
141 return vp!=tPtr->viewPosition;
145 static void
146 decrToFit(TextField *tPtr)
148 while (TEXT_WIDTH(tPtr, tPtr->viewPosition-1) < tPtr->usableWidth
149 && tPtr->viewPosition>0)
150 tPtr->viewPosition--;
153 #undef TEXT_WIDTH
154 #undef TEXT_WIDTH2
157 WMTextField*
158 WMCreateTextField(WMWidget *parent)
160 TextField *tPtr;
163 tPtr = wmalloc(sizeof(TextField));
164 memset(tPtr, 0, sizeof(TextField));
166 tPtr->widgetClass = WC_TextField;
168 tPtr->view = W_CreateView(W_VIEW(parent));
169 if (!tPtr->view) {
170 free(tPtr);
171 return NULL;
173 tPtr->view->self = tPtr;
175 tPtr->view->attribFlags |= CWCursor;
176 tPtr->view->attribs.cursor = tPtr->view->screen->textCursor;
178 W_SetViewBackgroundColor(tPtr->view, tPtr->view->screen->white);
180 tPtr->text = wmalloc(MIN_TEXT_BUFFER);
181 tPtr->text[0] = 0;
182 tPtr->textLen = 0;
183 tPtr->bufferSize = MIN_TEXT_BUFFER;
185 tPtr->flags.enabled = 1;
187 WMCreateEventHandler(tPtr->view, ExposureMask|StructureNotifyMask
188 |FocusChangeMask, handleEvents, tPtr);
190 W_ResizeView(tPtr->view, DEFAULT_WIDTH, DEFAULT_HEIGHT);
191 WMSetTextFieldBordered(tPtr, DEFAULT_BORDERED);
192 tPtr->flags.alignment = DEFAULT_ALIGNMENT;
193 tPtr->offsetWidth = (tPtr->view->size.height
194 - tPtr->view->screen->normalFont->height)/2;
196 WMCreateEventHandler(tPtr->view, EnterWindowMask|LeaveWindowMask
197 |ButtonPressMask|KeyPressMask|Button1MotionMask,
198 handleTextFieldActionEvents, tPtr);
200 tPtr->flags.cursorOn = 1;
202 return tPtr;
206 void
207 WMInsertTextFieldText(WMTextField *tPtr, char *text, int position)
209 int len;
211 CHECK_CLASS(tPtr, WC_TextField);
213 if (!text)
214 return;
216 len = strlen(text);
218 /* check if buffer will hold the text */
219 if (len + tPtr->textLen >= tPtr->bufferSize) {
220 tPtr->bufferSize = tPtr->textLen + len + TEXT_BUFFER_INCR;
221 tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
224 if (position < 0 || position >= tPtr->textLen) {
225 /* append the text at the end */
226 strcat(tPtr->text, text);
228 incrToFit(tPtr);
230 tPtr->textLen += len;
231 tPtr->cursorPosition += len;
232 } else {
233 /* insert text at position */
234 memmv(&(tPtr->text[position+len]), &(tPtr->text[position]),
235 tPtr->textLen-position+1);
237 memcpy(&(tPtr->text[position]), text, len);
239 tPtr->textLen += len;
240 if (position >= tPtr->cursorPosition) {
241 tPtr->cursorPosition += len;
242 incrToFit2(tPtr);
243 } else {
244 incrToFit(tPtr);
248 paintTextField(tPtr);
252 void
253 WMDeleteTextFieldRange(WMTextField *tPtr, WMRange range)
255 CHECK_CLASS(tPtr, WC_TextField);
257 if (range.position >= tPtr->textLen)
258 return;
260 if (range.count < 1) {
261 if (range.position < 0)
262 range.position = 0;
263 tPtr->text[range.position] = 0;
264 tPtr->textLen = range.position;
266 tPtr->cursorPosition = 0;
267 tPtr->viewPosition = 0;
268 } else {
269 if (range.position + range.count > tPtr->textLen)
270 range.count = tPtr->textLen - range.position;
271 memmv(&(tPtr->text[range.position]), &(tPtr->text[range.position+range.count]),
272 tPtr->textLen - (range.position+range.count) + 1);
273 tPtr->textLen -= range.count;
275 if (tPtr->cursorPosition > range.position)
276 tPtr->cursorPosition -= range.count;
278 decrToFit(tPtr);
281 paintTextField(tPtr);
286 char*
287 WMGetTextFieldText(WMTextField *tPtr)
289 CHECK_CLASS(tPtr, WC_TextField);
291 return wstrdup(tPtr->text);
295 void
296 WMSetTextFieldText(WMTextField *tPtr, char *text)
298 if (text==NULL) {
299 tPtr->text[0] = 0;
300 tPtr->textLen = 0;
301 } else {
302 tPtr->textLen = strlen(text);
304 if (tPtr->textLen >= tPtr->bufferSize) {
305 tPtr->bufferSize = tPtr->textLen + TEXT_BUFFER_INCR;
306 tPtr->text = realloc(tPtr->text, tPtr->bufferSize);
308 strcpy(tPtr->text, text);
310 if (tPtr->textLen < tPtr->cursorPosition)
311 tPtr->cursorPosition = tPtr->textLen;
313 if (tPtr->view->flags.realized)
314 paintTextField(tPtr);
318 void
319 WMSetTextFieldAlignment(WMTextField *tPtr, WMAlignment alignment)
321 tPtr->flags.alignment = alignment;
322 if (alignment!=WALeft) {
323 wwarning("only left alignment is supported in textfields");
324 return;
327 if (tPtr->view->flags.realized) {
328 paintTextField(tPtr);
333 void
334 WMSetTextFieldBordered(WMTextField *tPtr, Bool bordered)
336 tPtr->flags.bordered = bordered;
338 if (tPtr->view->flags.realized) {
339 paintTextField(tPtr);
345 void
346 WMSetTextFieldSecure(WMTextField *tPtr, Bool flag)
348 tPtr->flags.secure = flag;
350 if (tPtr->view->flags.realized) {
351 paintTextField(tPtr);
356 void
357 WMSetTextFieldEnabled(WMTextField *tPtr, Bool flag)
359 tPtr->flags.enabled = flag;
361 if (tPtr->view->flags.realized) {
362 paintTextField(tPtr);
367 static void
368 resizeTextField(WMTextField *tPtr, unsigned int width, unsigned int height)
370 W_ResizeView(tPtr->view, width, height);
372 tPtr->offsetWidth = (tPtr->view->size.height
373 - tPtr->view->screen->normalFont->height)/2;
375 tPtr->usableWidth = tPtr->view->size.width - 2*tPtr->offsetWidth;
379 static void
380 paintCursor(TextField *tPtr)
382 int cx;
383 WMScreen *screen = tPtr->view->screen;
384 int textWidth;
386 cx = WMWidthOfString(screen->normalFont,
387 &(tPtr->text[tPtr->viewPosition]),
388 tPtr->cursorPosition-tPtr->viewPosition);
390 switch (tPtr->flags.alignment) {
391 case WARight:
392 textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
393 tPtr->textLen);
394 if (textWidth < tPtr->usableWidth)
395 cx += tPtr->offsetWidth + tPtr->usableWidth - textWidth;
396 else
397 cx += tPtr->offsetWidth;
398 break;
399 case WALeft:
400 cx += tPtr->offsetWidth;
401 break;
402 case WACenter:
403 textWidth = WMWidthOfString(screen->normalFont, tPtr->text,
404 tPtr->textLen);
405 if (textWidth < tPtr->usableWidth)
406 cx += tPtr->offsetWidth + (tPtr->usableWidth-textWidth)/2;
407 else
408 cx += tPtr->offsetWidth;
409 break;
412 XDrawRectangle(screen->display, tPtr->view->window, screen->xorGC,
413 cx, tPtr->offsetWidth, 1,
414 tPtr->view->size.height - 2*tPtr->offsetWidth - 1);
416 XDrawLine(screen->display, tPtr->view->window, screen->xorGC,
417 cx, tPtr->offsetWidth, cx,
418 tPtr->view->size.height - tPtr->offsetWidth - 1);
423 static void
424 drawRelief(WMView *view)
426 WMScreen *scr = view->screen;
427 Display *dpy = scr->display;
428 GC wgc;
429 GC lgc;
430 GC dgc;
431 int width = view->size.width;
432 int height = view->size.height;
434 wgc = W_GC(scr->white);
435 dgc = W_GC(scr->darkGray);
436 lgc = W_GC(scr->gray);
438 /* top left */
439 XDrawLine(dpy, view->window, dgc, 0, 0, width-1, 0);
440 XDrawLine(dpy, view->window, dgc, 0, 1, width-2, 1);
442 XDrawLine(dpy, view->window, dgc, 0, 0, 0, height-2);
443 XDrawLine(dpy, view->window, dgc, 1, 0, 1, height-3);
445 /* bottom right */
446 XDrawLine(dpy, view->window, wgc, 0, height-1, width-1, height-1);
447 XDrawLine(dpy, view->window, lgc, 1, height-2, width-2, height-2);
449 XDrawLine(dpy, view->window, wgc, width-1, 0, width-1, height-1);
450 XDrawLine(dpy, view->window, lgc, width-2, 1, width-2, height-3);
454 static void
455 paintTextField(TextField *tPtr)
457 W_Screen *screen = tPtr->view->screen;
458 W_View *view = tPtr->view;
459 int tx, ty, tw, th;
460 int bd;
461 int totalWidth;
464 if (!view->flags.realized || !view->flags.mapped)
465 return;
467 if (!tPtr->flags.bordered) {
468 bd = 0;
469 } else {
470 bd = 2;
473 totalWidth = tPtr->view->size.width - 2*bd;
475 if (tPtr->textLen > 0) {
476 tw = WMWidthOfString(screen->normalFont,
477 &(tPtr->text[tPtr->viewPosition]),
478 tPtr->textLen - tPtr->viewPosition);
480 th = screen->normalFont->height;
482 ty = tPtr->offsetWidth;
483 switch (tPtr->flags.alignment) {
484 case WALeft:
485 tx = tPtr->offsetWidth;
486 if (tw < tPtr->usableWidth)
487 XClearArea(screen->display, view->window, bd+tw, bd,
488 totalWidth-tw, view->size.height-2*bd,
489 False);
490 break;
492 case WACenter:
493 tx = tPtr->offsetWidth + (tPtr->usableWidth - tw) / 2;
494 if (tw < tPtr->usableWidth)
495 XClearArea(screen->display, view->window, bd, bd,
496 totalWidth, view->size.height-2*bd, False);
497 break;
499 default:
500 case WARight:
501 tx = tPtr->offsetWidth + tPtr->usableWidth - tw;
502 if (tw < tPtr->usableWidth)
503 XClearArea(screen->display, view->window, bd, bd,
504 totalWidth-tw, view->size.height-2*bd, False);
505 break;
508 if (!tPtr->flags.secure) {
509 if (!tPtr->flags.enabled)
510 WMSetColorInGC(screen->darkGray, screen->textFieldGC);
512 WMDrawImageString(screen, view->window, screen->textFieldGC,
513 screen->normalFont, tx, ty,
514 &(tPtr->text[tPtr->viewPosition]),
515 tPtr->textLen - tPtr->viewPosition);
517 if (!tPtr->flags.enabled)
518 WMSetColorInGC(screen->black, screen->textFieldGC);
520 } else {
521 XClearArea(screen->display, view->window, bd, bd, totalWidth,
522 view->size.height - 2*bd, False);
525 /* draw cursor */
526 if (tPtr->flags.focused && tPtr->flags.enabled && tPtr->flags.cursorOn) {
527 paintCursor(tPtr);
530 /* draw relief */
531 if (tPtr->flags.bordered) {
532 drawRelief(view);
537 #if 0
538 static void
539 blinkCursor(void *data)
541 TextField *tPtr = (TextField*)data;
543 if (tPtr->flags.cursorOn) {
544 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_OFF_DELAY, blinkCursor,
545 data);
546 } else {
547 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY, blinkCursor,
548 data);
550 paintCursor(tPtr);
551 tPtr->flags.cursorOn = !tPtr->flags.cursorOn;
553 #endif
555 static void
556 handleEvents(XEvent *event, void *data)
558 TextField *tPtr = (TextField*)data;
560 CHECK_CLASS(data, WC_TextField);
563 switch (event->type) {
564 case FocusIn:
565 if (W_FocusedViewOfToplevel(W_TopLevelOfView(tPtr->view))!=tPtr->view)
566 return;
567 tPtr->flags.focused = 1;
568 #if 0
569 if (!tPtr->timerID) {
570 tPtr->timerID = WMAddTimerHandler(CURSOR_BLINK_ON_DELAY,
571 blinkCursor, tPtr);
573 #endif
574 paintTextField(tPtr);
576 WMPostNotificationName(WMTextDidBeginEditingNotification, tPtr, NULL);
578 tPtr->flags.notIllegalMovement = 0;
579 break;
581 case FocusOut:
582 tPtr->flags.focused = 0;
583 #if 0
584 if (tPtr->timerID)
585 WMDeleteTimerHandler(tPtr->timerID);
586 tPtr->timerID = NULL;
587 #endif
589 paintTextField(tPtr);
590 if (!tPtr->flags.notIllegalMovement) {
591 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
592 (void*)WMIllegalTextMovement);
594 break;
596 case Expose:
597 if (event->xexpose.count!=0)
598 break;
599 paintTextField(tPtr);
600 break;
602 case DestroyNotify:
603 destroyTextField(tPtr);
604 break;
609 static void
610 handleTextFieldKeyPress(TextField *tPtr, XEvent *event)
612 char buffer[64];
613 KeySym ksym;
614 int count, refresh = 0;
615 int control_pressed = 0;
616 int changed;
617 WMScreen *scr = tPtr->view->screen;
619 changed = 0;
621 if (((XKeyEvent *) event)->state & WM_EMACSKEYMASK) {
622 control_pressed = 1;
625 count = XLookupString(&event->xkey, buffer, 63, &ksym, NULL);
626 buffer[count] = '\0';
628 switch (ksym) {
629 case XK_Tab:
630 if (event->xkey.state & ShiftMask) {
631 if (tPtr->view->prevFocusChain) {
632 W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
633 tPtr->view->prevFocusChain);
634 tPtr->flags.notIllegalMovement = 1;
636 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
637 (void*)WMBacktabTextMovement);
638 } else {
639 if (tPtr->view->nextFocusChain) {
640 W_SetFocusOfTopLevel(W_TopLevelOfView(tPtr->view),
641 tPtr->view->nextFocusChain);
642 tPtr->flags.notIllegalMovement = 1;
644 WMPostNotificationName(WMTextDidEndEditingNotification,
645 tPtr, (void*)WMTabTextMovement);
647 break;
649 case XK_Return:
650 WMPostNotificationName(WMTextDidEndEditingNotification, tPtr,
651 (void*)WMReturnTextMovement);
652 break;
654 case WM_EMACSKEY_LEFT:
655 if (!control_pressed) {
656 goto normal_key;
658 case XK_KP_Left:
659 case XK_Left:
660 if (tPtr->cursorPosition > 0) {
661 paintCursor(tPtr);
662 tPtr->cursorPosition--;
663 if (tPtr->cursorPosition < tPtr->viewPosition) {
664 tPtr->viewPosition = tPtr->cursorPosition;
665 refresh = 1;
666 } else {
667 paintCursor(tPtr);
670 break;
672 case WM_EMACSKEY_RIGHT:
673 if (!control_pressed) {
674 goto normal_key;
676 case XK_KP_Right:
677 case XK_Right:
678 if (tPtr->cursorPosition < tPtr->textLen) {
679 paintCursor(tPtr);
680 tPtr->cursorPosition++;
681 while (WMWidthOfString(scr->normalFont,
682 &(tPtr->text[tPtr->viewPosition]),
683 tPtr->cursorPosition-tPtr->viewPosition)
684 > tPtr->usableWidth) {
685 tPtr->viewPosition++;
686 refresh = 1;
688 if (!refresh)
689 paintCursor(tPtr);
691 break;
693 case WM_EMACSKEY_HOME:
694 if (!control_pressed) {
695 goto normal_key;
697 case XK_KP_Home:
698 case XK_Home:
699 if (tPtr->cursorPosition > 0) {
700 paintCursor(tPtr);
701 tPtr->cursorPosition = 0;
702 if (tPtr->viewPosition > 0) {
703 tPtr->viewPosition = 0;
704 refresh = 1;
705 } else {
706 paintCursor(tPtr);
709 break;
711 case WM_EMACSKEY_END:
712 if (!control_pressed) {
713 goto normal_key;
715 case XK_KP_End:
716 case XK_End:
717 if (tPtr->cursorPosition < tPtr->textLen) {
718 paintCursor(tPtr);
719 tPtr->cursorPosition = tPtr->textLen;
720 tPtr->viewPosition = 0;
721 while (WMWidthOfString(scr->normalFont,
722 &(tPtr->text[tPtr->viewPosition]),
723 tPtr->textLen-tPtr->viewPosition)
724 >= tPtr->usableWidth) {
725 tPtr->viewPosition++;
726 refresh = 1;
728 if (!refresh)
729 paintCursor(tPtr);
731 break;
733 case WM_EMACSKEY_BS:
734 if (!control_pressed) {
735 goto normal_key;
737 case XK_BackSpace:
738 if (tPtr->cursorPosition > 0) {
739 WMRange range;
740 changed = 1;
741 range.position = tPtr->cursorPosition-1;
742 range.count = 1;
743 WMDeleteTextFieldRange(tPtr, range);
745 break;
747 case WM_EMACSKEY_DEL:
748 if (!control_pressed) {
749 goto normal_key;
751 case XK_KP_Delete:
752 case XK_Delete:
753 if (tPtr->cursorPosition < tPtr->textLen) {
754 WMRange range;
755 changed = 1;
756 range.position = tPtr->cursorPosition;
757 range.count = 1;
758 WMDeleteTextFieldRange(tPtr, range);
760 break;
762 normal_key:
763 default:
764 if (count > 0 && !iscntrl(buffer[0])) {
765 changed = 1;
766 WMInsertTextFieldText(tPtr, buffer, tPtr->cursorPosition);
769 if (refresh) {
770 paintTextField(tPtr);
773 if (changed) {
774 WMPostNotificationName(WMTextDidChangeNotification, tPtr, NULL);
779 static int
780 pointToCursorPosition(TextField *tPtr, int x)
782 WMFont *font = tPtr->view->screen->normalFont;
783 int a, b, mid;
784 int tw;
786 if (tPtr->flags.bordered)
787 x -= 2;
789 a = tPtr->viewPosition;
790 b = tPtr->viewPosition + tPtr->textLen;
791 if (WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
792 tPtr->textLen-tPtr->viewPosition) < x)
793 return tPtr->textLen;
795 while (a < b && b-a>1) {
796 mid = (a+b)/2;
797 tw = WMWidthOfString(font, &(tPtr->text[tPtr->viewPosition]),
798 mid - tPtr->viewPosition);
799 if (tw > x)
800 b = mid;
801 else if (tw < x)
802 a = mid;
803 else
804 return mid;
806 return (a+b)/2;
810 static void
811 handleTextFieldActionEvents(XEvent *event, void *data)
813 TextField *tPtr = (TextField*)data;
815 CHECK_CLASS(data, WC_TextField);
817 switch (event->type) {
818 case KeyPress:
819 if (tPtr->flags.enabled)
820 handleTextFieldKeyPress(tPtr, event);
821 break;
823 case MotionNotify:
824 if (tPtr->flags.enabled && (event->xmotion.state & Button1Mask)) {
825 tPtr->cursorPosition = pointToCursorPosition(tPtr,
826 event->xmotion.x);
827 paintTextField(tPtr);
829 break;
831 case ButtonPress:
832 if (tPtr->flags.enabled && !tPtr->flags.focused) {
833 WMSetFocusToWidget(tPtr);
834 tPtr->cursorPosition = pointToCursorPosition(tPtr,
835 event->xbutton.x);
836 paintTextField(tPtr);
837 } else if (tPtr->flags.focused) {
838 tPtr->cursorPosition = pointToCursorPosition(tPtr,
839 event->xbutton.x);
840 paintTextField(tPtr);
842 if (event->xbutton.button == Button2 && tPtr->flags.enabled) {
843 char *text;
845 text = W_GetTextSelection(tPtr->view->screen, XA_PRIMARY);
846 if (!text) {
847 text = W_GetTextSelection(tPtr->view->screen, XA_CUT_BUFFER0);
849 if (text) {
850 WMInsertTextFieldText(tPtr, text, tPtr->cursorPosition);
851 XFree(text);
852 WMPostNotificationName(WMTextDidChangeNotification, tPtr,
853 NULL);
856 break;
858 case ButtonRelease:
860 break;
865 static void
866 destroyTextField(TextField *tPtr)
868 #if 0
869 if (tPtr->timerID)
870 WMDeleteTimerHandler(tPtr->timerID);
871 #endif
873 if (tPtr->text)
874 free(tPtr->text);
876 free(tPtr);