Remove hard limitation that AI wonder cities never build settlers
[freeciv.git] / client / gui-sdl2 / widget_edit.c
blob9fc48b6a2f4db8becfcc84a94d18062b40124ba1
1 /***********************************************************************
2 Freeciv - Copyright (C) 2006 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* SDL2 */
19 #ifdef SDL2_PLAIN_INCLUDE
20 #include <SDL.h>
21 #else /* SDL2_PLAIN_INCLUDE */
22 #include <SDL2/SDL.h>
23 #endif /* SDL2_PLAIN_INCLUDE */
25 /* gui-sdl2 */
26 #include "colors.h"
27 #include "graphics.h"
28 #include "gui_iconv.h"
29 #include "gui_id.h"
30 #include "gui_tilespec.h"
31 #include "mapview.h"
32 #include "themespec.h"
33 #include "unistring.h"
34 #include "utf8string.h"
35 #include "widget.h"
36 #include "widget_p.h"
38 struct Utf8Char {
39 struct Utf8Char *next;
40 struct Utf8Char *prev;
41 int bytes;
42 char chr[7];
43 SDL_Surface *pTsurf;
46 struct EDIT {
47 struct Utf8Char *pBeginTextChain;
48 struct Utf8Char *pEndTextChain;
49 struct Utf8Char *pInputChain;
50 SDL_Surface *pBg;
51 struct widget *pWidget;
52 int ChainLen;
53 int Start_X;
54 int Truelength;
55 int InputChain_X;
58 static size_t chainlen(const struct Utf8Char *pChain);
59 static void del_chain(struct Utf8Char *pChain);
60 static struct Utf8Char *text2chain(const char *text_in);
61 static char *chain2text(const struct Utf8Char *pInChain, size_t len, size_t *size);
63 static int (*baseclass_redraw)(struct widget *pwidget);
65 /**************************************************************************
66 Draw the text being edited.
67 **************************************************************************/
68 static int redraw_edit_chain(struct EDIT *pEdt)
70 struct Utf8Char *pInputChain_TMP;
71 SDL_Rect Dest, Dest_Copy = {0, 0, 0, 0};
72 int iStart_Mod_X;
73 int ret;
75 Dest_Copy.x = pEdt->pWidget->size.x;
76 Dest_Copy.y = pEdt->pWidget->size.y;
78 ret = (*baseclass_redraw)(pEdt->pWidget);
79 if (ret != 0) {
80 return ret;
83 /* blit theme */
84 Dest = Dest_Copy;
86 alphablit(pEdt->pBg, NULL, pEdt->pWidget->dst->surface, &Dest, 255);
88 /* set start parameters */
89 pInputChain_TMP = pEdt->pBeginTextChain;
90 iStart_Mod_X = 0;
92 Dest_Copy.y += (pEdt->pBg->h - pInputChain_TMP->pTsurf->h) / 2;
93 Dest_Copy.x += pEdt->Start_X;
95 /* draw loop */
96 while (pInputChain_TMP) {
97 Dest_Copy.x += iStart_Mod_X;
98 /* chech if we draw inside of edit rect */
99 if (Dest_Copy.x > pEdt->pWidget->size.x + pEdt->pBg->w - 4) {
100 break;
103 if (Dest_Copy.x > pEdt->pWidget->size.x) {
104 Dest = Dest_Copy;
105 alphablit(pInputChain_TMP->pTsurf, NULL, pEdt->pWidget->dst->surface, &Dest,
106 255);
109 iStart_Mod_X = pInputChain_TMP->pTsurf->w;
111 /* draw cursor */
112 if (pInputChain_TMP == pEdt->pInputChain) {
113 Dest = Dest_Copy;
115 create_line(pEdt->pWidget->dst->surface,
116 Dest.x - 1, Dest.y + (pEdt->pBg->h / 8),
117 Dest.x - 1, Dest.y + pEdt->pBg->h - (pEdt->pBg->h / 4),
118 get_theme_color(COLOR_THEME_EDITFIELD_CARET));
119 /* save active element position */
120 pEdt->InputChain_X = Dest_Copy.x;
123 pInputChain_TMP = pInputChain_TMP->next;
124 } /* while - draw loop */
126 widget_flush(pEdt->pWidget);
128 return 0;
131 /**************************************************************************
132 Create Edit Field surface ( with Text) and blit them to Main.screen,
133 on position 'pEdit_Widget->size.x , pEdit_Widget->size.y'
135 Graphic is taken from 'pEdit_Widget->theme'
136 Text is taken from 'pEdit_Widget->string_utf8'
138 if flag 'FW_DRAW_THEME_TRANSPARENT' is set theme will be blit
139 transparent ( Alpha = 128 )
141 function return Hight of created surfaces or (-1) if theme surface can't
142 be created.
143 **************************************************************************/
144 static int redraw_edit(struct widget *pEdit_Widget)
146 int ret;
148 if (get_wstate(pEdit_Widget) == FC_WS_PRESSED) {
149 return redraw_edit_chain((struct EDIT *)pEdit_Widget->data.ptr);
150 } else {
151 int iRet = 0;
152 SDL_Rect rDest = {pEdit_Widget->size.x, pEdit_Widget->size.y, 0, 0};
153 SDL_Surface *pEdit = NULL;
154 SDL_Surface *pText;
156 ret = (*baseclass_redraw)(pEdit_Widget);
157 if (ret != 0) {
158 return ret;
161 if (pEdit_Widget->string_utf8->text != NULL
162 && get_wflags(pEdit_Widget) & WF_PASSWD_EDIT) {
163 char *backup = pEdit_Widget->string_utf8->text;
164 size_t len = strlen(backup) + 1;
165 char *cbuf = fc_calloc(1, len);
167 memset(cbuf, '*', len - 1);
168 cbuf[len - 1] = '\0';
169 pEdit_Widget->string_utf8->text = cbuf;
170 pText = create_text_surf_from_utf8(pEdit_Widget->string_utf8);
171 FC_FREE(cbuf);
172 pEdit_Widget->string_utf8->text = backup;
173 } else {
174 pText = create_text_surf_from_utf8(pEdit_Widget->string_utf8);
177 pEdit = create_bcgnd_surf(pEdit_Widget->theme, get_wstate(pEdit_Widget),
178 pEdit_Widget->size.w, pEdit_Widget->size.h);
180 if (!pEdit) {
181 return -1;
184 /* blit theme */
185 alphablit(pEdit, NULL, pEdit_Widget->dst->surface, &rDest, 255);
187 /* set position and blit text */
188 if (pText) {
189 rDest.y += (pEdit->h - pText->h) / 2;
190 /* blit centred text to botton */
191 if (pEdit_Widget->string_utf8->style & SF_CENTER) {
192 rDest.x += (pEdit->w - pText->w) / 2;
193 } else {
194 if (pEdit_Widget->string_utf8->style & SF_CENTER_RIGHT) {
195 rDest.x += pEdit->w - pText->w - adj_size(5);
196 } else {
197 rDest.x += adj_size(5); /* center left */
201 alphablit(pText, NULL, pEdit_Widget->dst->surface, &rDest, 255);
203 /* pText */
204 iRet = pEdit->h;
206 /* Free memory */
207 FREESURFACE(pText);
208 FREESURFACE(pEdit);
210 return iRet;
213 return 0;
216 /**************************************************************************
217 Return length of Utf8Char chain.
218 WARRNING: if struct Utf8Char has 1 member and Utf8Char->chr == 0 then
219 this function return 1 ( not 0 like in strlen )
220 **************************************************************************/
221 static size_t chainlen(const struct Utf8Char *pChain)
223 size_t length = 0;
225 if (pChain) {
226 while (TRUE) {
227 length++;
228 if (pChain->next == NULL) {
229 break;
231 pChain = pChain->next;
235 return length;
238 /**************************************************************************
239 Delete Utf8Char structure.
240 **************************************************************************/
241 static void del_chain(struct Utf8Char *pChain)
243 int i, len = 0;
245 if (!pChain) {
246 return;
249 len = chainlen(pChain);
251 if (len > 1) {
252 pChain = pChain->next;
253 for (i = 0; i < len - 1; i++) {
254 FREESURFACE(pChain->prev->pTsurf);
255 FC_FREE(pChain->prev);
256 pChain = pChain->next;
260 FC_FREE(pChain);
263 /**************************************************************************
264 Convert utf8 string to Utf8Char structure.
265 Memory alocation -> after all use need call del_chain(...) !
266 **************************************************************************/
267 static struct Utf8Char *text2chain(const char *text_in)
269 int i, len;
270 struct Utf8Char *out_chain = NULL;
271 struct Utf8Char *chr_tmp = NULL;
272 int j;
274 if (text_in == NULL) {
275 return NULL;
278 len = strlen(text_in);
280 if (len == 0) {
281 return NULL;
284 out_chain = fc_calloc(1, sizeof(struct Utf8Char));
285 out_chain->chr[0] = text_in[0];
286 for (j = 1; (text_in[j] & (128 + 64)) == 128; j++) {
287 out_chain->chr[j] = text_in[j];
289 out_chain->bytes = j;
290 chr_tmp = out_chain;
292 for (i = 1; i < len; i += j) {
293 chr_tmp->next = fc_calloc(1, sizeof(struct Utf8Char));
294 chr_tmp->next->chr[0] = text_in[i];
295 for (j = 1; (text_in[i + j] & (128 + 64)) == 128; j++) {
296 chr_tmp->next->chr[j] = text_in[i + j];
298 chr_tmp->next->bytes = j;
299 chr_tmp->next->prev = chr_tmp;
300 chr_tmp = chr_tmp->next;
303 return out_chain;
306 /**************************************************************************
307 Convert Utf8Char structure to chars
308 WARNING: Do not free Utf8Char structure but allocates new char array.
309 **************************************************************************/
310 static char *chain2text(const struct Utf8Char *pInChain, size_t len,
311 size_t *size)
313 int i;
314 char *pOutText = NULL;
315 int oi = 0;
316 int total_size = 0;
318 if (!(len && pInChain)) {
319 return pOutText;
322 pOutText = fc_calloc(8, len + 1);
323 for (i = 0; i < len; i++) {
324 int j;
326 for (j = 0; j < pInChain->bytes && i < len; j++) {
327 pOutText[oi++] = pInChain->chr[j];
330 total_size += pInChain->bytes;
331 pInChain = pInChain->next;
334 *size = total_size;
336 return pOutText;
339 /* =================================================== */
341 /**************************************************************************
342 Create ( malloc ) Edit Widget structure.
344 Edit Theme graphic is taken from current_theme->Edit surface;
345 Text is taken from 'pstr'.
347 'length' parameter determinate width of Edit rect.
349 This function determinate future size of Edit ( width, height ) and
350 save this in: pWidget->size rectangle ( SDL_Rect )
352 function return pointer to allocated Edit Widget.
353 **************************************************************************/
354 struct widget *create_edit(SDL_Surface *pBackground, struct gui_layer *pDest,
355 utf8_str *pstr, int length, Uint32 flags)
357 SDL_Rect buf = {0, 0, 0, 0};
358 struct widget *pEdit = widget_new();
360 pEdit->theme = current_theme->Edit;
361 pEdit->theme2 = pBackground; /* FIXME: make somewhere use of it */
362 pEdit->string_utf8 = pstr;
363 set_wflag(pEdit, (WF_FREE_STRING | WF_FREE_GFX | flags));
364 set_wstate(pEdit, FC_WS_DISABLED);
365 set_wtype(pEdit, WT_EDIT);
366 pEdit->mod = KMOD_NONE;
368 baseclass_redraw = pEdit->redraw;
369 pEdit->redraw = redraw_edit;
371 if (pstr != NULL) {
372 pEdit->string_utf8->style |= SF_CENTER;
373 utf8_str_size(pstr, &buf);
374 buf.h += adj_size(4);
377 length = MAX(length, buf.w + adj_size(10));
379 correct_size_bcgnd_surf(current_theme->Edit, &length, &buf.h);
381 pEdit->size.w = length;
382 pEdit->size.h = buf.h;
384 if (pDest) {
385 pEdit->dst = pDest;
386 } else {
387 pEdit->dst = add_gui_layer(pEdit->size.w, pEdit->size.h);
390 return pEdit;
393 /**************************************************************************
394 set new x, y position and redraw edit.
395 **************************************************************************/
396 int draw_edit(struct widget *pEdit, Sint16 start_x, Sint16 start_y)
398 pEdit->size.x = start_x;
399 pEdit->size.y = start_y;
401 if (get_wflags(pEdit) & WF_RESTORE_BACKGROUND) {
402 refresh_widget_background(pEdit);
405 return redraw_edit(pEdit);
408 /**************************************************************************
409 This functions are pure madness :)
410 Create Edit Field surface ( with Text) and blit them to Main.screen,
411 on position 'pEdit_Widget->size.x , pEdit_Widget->size.y'
413 Main role of this functions are been text input to GUI.
414 This code allow you to add, del unichar from unistring.
416 Graphic is taken from 'pEdit_Widget->theme'
417 OldText is taken from 'pEdit_Widget->string_utf8'
419 NewText is returned to 'pEdit_Widget->string_utf8' ( after free OldText )
421 if flag 'FW_DRAW_THEME_TRANSPARENT' is set theme will be blit
422 transparent ( Alpha = 128 )
424 NOTE: This functions can return NULL in 'pEdit_Widget->string_utf8->text' but
425 never free 'pEdit_Widget->string_utf8' struct.
426 **************************************************************************/
427 static Uint16 edit_key_down(SDL_Keysym key, void *pData)
429 struct EDIT *pEdt = (struct EDIT *)pData;
430 struct Utf8Char *pInputChain_TMP;
431 bool Redraw = FALSE;
433 /* find which key is pressed */
434 switch (key.sym) {
435 case SDLK_ESCAPE:
436 /* exit from loop without changes */
437 return ED_ESC;
438 case SDLK_RETURN:
439 case SDLK_KP_ENTER:
440 /* exit from loop */
441 return ED_RETURN;
443 case SDLK_KP6:
444 if (key.mod & KMOD_NUM) {
445 goto INPUT;
448 case SDLK_RIGHT:
450 /* move cursor right */
451 if (pEdt->pInputChain->next) {
452 if (pEdt->InputChain_X >= (pEdt->pWidget->size.x + pEdt->pBg->w - adj_size(10))) {
453 pEdt->Start_X -= pEdt->pInputChain->pTsurf->w -
454 (pEdt->pWidget->size.x + pEdt->pBg->w - adj_size(5) - pEdt->InputChain_X);
457 pEdt->pInputChain = pEdt->pInputChain->next;
458 Redraw = TRUE;
461 break;
463 case SDLK_KP4:
464 if (key.mod & KMOD_NUM) {
465 goto INPUT;
468 case SDLK_LEFT:
470 /* move cursor left */
471 if (pEdt->pInputChain->prev) {
472 pEdt->pInputChain = pEdt->pInputChain->prev;
473 if ((pEdt->InputChain_X <=
474 (pEdt->pWidget->size.x + adj_size(9))) && (pEdt->Start_X != adj_size(5))) {
475 if (pEdt->InputChain_X != (pEdt->pWidget->size.x + adj_size(5))) {
476 pEdt->Start_X += (pEdt->pWidget->size.x - pEdt->InputChain_X + adj_size(5));
479 pEdt->Start_X += (pEdt->pInputChain->pTsurf->w);
481 Redraw = TRUE;
484 break;
486 case SDLK_KP7:
487 if (key.mod & KMOD_NUM) {
488 goto INPUT;
491 case SDLK_HOME:
493 /* move cursor to begin of chain (and edit field) */
494 pEdt->pInputChain = pEdt->pBeginTextChain;
495 Redraw = TRUE;
496 pEdt->Start_X = adj_size(5);
498 break;
500 case SDLK_KP1:
501 if (key.mod & KMOD_NUM) {
502 goto INPUT;
505 case SDLK_END:
507 /* move cursor to end of chain (and edit field) */
508 pEdt->pInputChain = pEdt->pEndTextChain;
509 Redraw = TRUE;
511 if (pEdt->pWidget->size.w - pEdt->Truelength < 0) {
512 pEdt->Start_X = pEdt->pWidget->size.w - pEdt->Truelength - adj_size(5);
515 break;
516 case SDLK_BACKSPACE:
518 /* del element of chain (and move cursor left) */
519 if (pEdt->pInputChain->prev) {
520 if ((pEdt->InputChain_X <=
521 (pEdt->pWidget->size.x + adj_size(9))) && (pEdt->Start_X != adj_size(5))) {
522 if (pEdt->InputChain_X != (pEdt->pWidget->size.x + adj_size(5))) {
523 pEdt->Start_X += (pEdt->pWidget->size.x - pEdt->InputChain_X + adj_size(5));
525 pEdt->Start_X += (pEdt->pInputChain->prev->pTsurf->w);
528 if (pEdt->pInputChain->prev->prev) {
529 pEdt->pInputChain->prev->prev->next = pEdt->pInputChain;
530 pInputChain_TMP = pEdt->pInputChain->prev->prev;
531 pEdt->Truelength -= pEdt->pInputChain->prev->pTsurf->w;
532 FREESURFACE(pEdt->pInputChain->prev->pTsurf);
533 FC_FREE(pEdt->pInputChain->prev);
534 pEdt->pInputChain->prev = pInputChain_TMP;
535 } else {
536 pEdt->Truelength -= pEdt->pInputChain->prev->pTsurf->w;
537 FREESURFACE(pEdt->pInputChain->prev->pTsurf);
538 FC_FREE(pEdt->pInputChain->prev);
539 pEdt->pBeginTextChain = pEdt->pInputChain;
542 pEdt->ChainLen--;
543 Redraw = TRUE;
546 break;
548 case SDLK_KP_PERIOD:
549 if (key.mod & KMOD_NUM) {
550 goto INPUT;
553 case SDLK_DELETE:
555 /* del element of chain */
556 if (pEdt->pInputChain->next && pEdt->pInputChain->prev) {
557 pEdt->pInputChain->prev->next = pEdt->pInputChain->next;
558 pEdt->pInputChain->next->prev = pEdt->pInputChain->prev;
559 pInputChain_TMP = pEdt->pInputChain->next;
560 pEdt->Truelength -= pEdt->pInputChain->pTsurf->w;
561 FREESURFACE(pEdt->pInputChain->pTsurf);
562 FC_FREE(pEdt->pInputChain);
563 pEdt->pInputChain = pInputChain_TMP;
564 pEdt->ChainLen--;
565 Redraw = TRUE;
568 if (pEdt->pInputChain->next && !pEdt->pInputChain->prev) {
569 pEdt->pInputChain = pEdt->pInputChain->next;
570 pEdt->Truelength -= pEdt->pInputChain->prev->pTsurf->w;
571 FREESURFACE(pEdt->pInputChain->prev->pTsurf);
572 FC_FREE(pEdt->pInputChain->prev);
573 pEdt->pBeginTextChain = pEdt->pInputChain;
574 pEdt->ChainLen--;
575 Redraw = TRUE;
578 break;
579 default:
580 break;
581 } /* key pressed switch */
583 if (Redraw) {
584 redraw_edit_chain(pEdt);
587 return ID_ERROR;
590 /**************************************************************************
591 Handle textinput strings coming to the edit widget
592 **************************************************************************/
593 static Uint16 edit_textinput(char *text, void *pData)
595 struct EDIT *pEdt = (struct EDIT *)pData;
596 struct Utf8Char *pInputChain_TMP;
597 int i;
599 for (i = 0; text[i] != '\0';) {
600 int charlen = 1;
601 unsigned char leading = text[i++];
602 int sum = 128 + 64;
603 int addition = 32;
605 /* add new element of chain (and move cursor right) */
606 if (pEdt->pInputChain != pEdt->pBeginTextChain) {
607 pInputChain_TMP = pEdt->pInputChain->prev;
608 pEdt->pInputChain->prev = fc_calloc(1, sizeof(struct Utf8Char));
609 pEdt->pInputChain->prev->next = pEdt->pInputChain;
610 pEdt->pInputChain->prev->prev = pInputChain_TMP;
611 pInputChain_TMP->next = pEdt->pInputChain->prev;
612 } else {
613 pEdt->pInputChain->prev = fc_calloc(1, sizeof(struct Utf8Char));
614 pEdt->pInputChain->prev->next = pEdt->pInputChain;
615 pEdt->pBeginTextChain = pEdt->pInputChain->prev;
618 pEdt->pInputChain->prev->chr[0] = leading;
619 /* UTF-8 multibyte handling */
620 while (leading >= sum) {
621 pEdt->pInputChain->prev->chr[charlen++] = text[i++];
622 sum += addition;
623 addition /= 2;
625 pEdt->pInputChain->prev->chr[charlen] = '\0';
626 pEdt->pInputChain->prev->bytes = charlen;
628 if (get_wflags(pEdt->pWidget) & WF_PASSWD_EDIT) {
629 char passwd_chr[2] = {'*', '\0'};
631 pEdt->pInputChain->prev->pTsurf =
632 TTF_RenderUTF8_Blended(pEdt->pWidget->string_utf8->font,
633 passwd_chr,
634 pEdt->pWidget->string_utf8->fgcol);
635 } else {
636 pEdt->pInputChain->prev->pTsurf =
637 TTF_RenderUTF8_Blended(pEdt->pWidget->string_utf8->font,
638 pEdt->pInputChain->prev->chr,
639 pEdt->pWidget->string_utf8->fgcol);
641 pEdt->Truelength += pEdt->pInputChain->prev->pTsurf->w;
643 if (pEdt->InputChain_X >= pEdt->pWidget->size.x + pEdt->pBg->w - adj_size(10)) {
644 if (pEdt->pInputChain == pEdt->pEndTextChain) {
645 pEdt->Start_X = pEdt->pBg->w - adj_size(5) - pEdt->Truelength;
646 } else {
647 pEdt->Start_X -= pEdt->pInputChain->prev->pTsurf->w -
648 (pEdt->pWidget->size.x + pEdt->pBg->w - adj_size(5) - pEdt->InputChain_X);
652 pEdt->ChainLen++;
655 redraw_edit_chain(pEdt);
657 return ID_ERROR;
660 /**************************************************************************
661 Handle mouse down events on edit widget.
662 **************************************************************************/
663 static Uint16 edit_mouse_button_down(SDL_MouseButtonEvent *pButtonEvent,
664 void *pData)
666 struct EDIT *pEdt = (struct EDIT *)pData;
668 if (pButtonEvent->button == SDL_BUTTON_LEFT) {
669 if (!(pButtonEvent->x >= pEdt->pWidget->size.x
670 && pButtonEvent->x < pEdt->pWidget->size.x + pEdt->pBg->w
671 && pButtonEvent->y >= pEdt->pWidget->size.y
672 && pButtonEvent->y < pEdt->pWidget->size.y + pEdt->pBg->h)) {
673 /* exit from loop */
674 return (Uint16)ED_MOUSE;
678 return (Uint16)ID_ERROR;
681 /**************************************************************************
682 Handle active edit. Returns what should happen to the edit
683 next.
684 **************************************************************************/
685 enum Edit_Return_Codes edit_field(struct widget *pEdit_Widget)
687 struct EDIT pEdt;
688 struct Utf8Char ___last;
689 struct Utf8Char *pInputChain_TMP = NULL;
690 enum Edit_Return_Codes ret;
691 void *backup = pEdit_Widget->data.ptr;
693 pEdt.pWidget = pEdit_Widget;
694 pEdt.ChainLen = 0;
695 pEdt.Truelength = 0;
696 pEdt.Start_X = adj_size(5);
697 pEdt.InputChain_X = 0;
699 pEdit_Widget->data.ptr = (void *)&pEdt;
701 #if 0
702 SDL_EnableUNICODE(1);
703 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
704 #endif /* 0 */
706 pEdt.pBg = create_bcgnd_surf(pEdit_Widget->theme, 2,
707 pEdit_Widget->size.w, pEdit_Widget->size.h);
709 /* Creating Chain */
710 pEdt.pBeginTextChain = text2chain(pEdit_Widget->string_utf8->text);
712 /* Creating Empty (Last) pice of Chain */
713 pEdt.pInputChain = &___last;
714 pEdt.pEndTextChain = pEdt.pInputChain;
715 pEdt.pEndTextChain->chr[0] = 32; /* spacebar */
716 pEdt.pEndTextChain->chr[1] = 0; /* spacebar */
717 pEdt.pEndTextChain->next = NULL;
718 pEdt.pEndTextChain->prev = NULL;
720 /* set font style (if any ) */
721 if (!((pEdit_Widget->string_utf8->style & 0x0F) & TTF_STYLE_NORMAL)) {
722 TTF_SetFontStyle(pEdit_Widget->string_utf8->font,
723 (pEdit_Widget->string_utf8->style & 0x0F));
726 pEdt.pEndTextChain->pTsurf =
727 TTF_RenderUTF8_Blended(pEdit_Widget->string_utf8->font,
728 pEdt.pEndTextChain->chr,
729 pEdit_Widget->string_utf8->fgcol);
731 /* create surface for each font in chain and find chain length */
732 if (pEdt.pBeginTextChain) {
733 pInputChain_TMP = pEdt.pBeginTextChain;
735 while (TRUE) {
736 pEdt.ChainLen++;
738 if (get_wflags(pEdit_Widget) & WF_PASSWD_EDIT) {
739 const char passwd_chr[2] = {'*', '\0'};
741 pInputChain_TMP->pTsurf =
742 TTF_RenderUTF8_Blended(pEdit_Widget->string_utf8->font,
743 passwd_chr,
744 pEdit_Widget->string_utf8->fgcol);
745 } else {
746 pInputChain_TMP->pTsurf =
747 TTF_RenderUTF8_Blended(pEdit_Widget->string_utf8->font,
748 pInputChain_TMP->chr,
749 pEdit_Widget->string_utf8->fgcol);
752 pEdt.Truelength += pInputChain_TMP->pTsurf->w;
754 if (pInputChain_TMP->next == NULL) {
755 break;
758 pInputChain_TMP = pInputChain_TMP->next;
760 /* set terminator of list */
761 pInputChain_TMP->next = pEdt.pInputChain;
762 pEdt.pInputChain->prev = pInputChain_TMP;
763 pInputChain_TMP = NULL;
764 } else {
765 pEdt.pBeginTextChain = pEdt.pInputChain;
768 redraw_edit_chain(&pEdt);
770 set_wstate(pEdit_Widget, FC_WS_PRESSED);
772 /* local loop */
773 Uint16 rety = gui_event_loop((void *)&pEdt, NULL,
774 edit_key_down, NULL, edit_textinput,
775 edit_mouse_button_down, NULL, NULL);
777 if (pEdt.pBeginTextChain == pEdt.pEndTextChain) {
778 pEdt.pBeginTextChain = NULL;
781 if (rety == MAX_ID) {
782 ret = ED_FORCE_EXIT;
783 } else {
784 ret = (enum Edit_Return_Codes) rety;
786 /* this is here because we have no knowledge that pEdit_Widget exist
787 or nor in force exit mode from gui loop */
789 /* reset font settings */
790 if (!((pEdit_Widget->string_utf8->style & 0x0F) & TTF_STYLE_NORMAL)) {
791 TTF_SetFontStyle(pEdit_Widget->string_utf8->font, TTF_STYLE_NORMAL);
794 if (ret != ED_ESC) {
795 size_t len = 0;
797 FC_FREE(pEdit_Widget->string_utf8->text);
798 pEdit_Widget->string_utf8->text =
799 chain2text(pEdt.pBeginTextChain, pEdt.ChainLen, &len);
800 pEdit_Widget->string_utf8->n_alloc = len + 1;
803 pEdit_Widget->data.ptr = backup;
804 set_wstate(pEdit_Widget, FC_WS_NORMAL);
808 FREESURFACE(pEdt.pEndTextChain->pTsurf);
810 del_chain(pEdt.pBeginTextChain);
812 FREESURFACE(pEdt.pBg);
814 /* disable repeat key */
816 #if 0
817 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
819 /* disable Unicode */
820 SDL_EnableUNICODE(0);
821 #endif /* 0 */
823 return ret;