(svn r5944) -Merge TGP (r5578, r5579, r5724, r5726): -Feature: filter for textboxes to only
authortruelight
Sat, 19 Aug 2006 09:31:22 +0000
changeset 4299 91f5d2bedcff
parent 4298 b926a6eaaa70
child 4300 c7e43c47a2b9
(svn r5944) -Merge TGP (r5578, r5579, r5724, r5726): -Feature: filter for textboxes to only
allow certain patterns (like numbers only)
aircraft_gui.c
console.c
gui.h
industry_gui.c
main_gui.c
misc_gui.c
network_gui.c
newgrf_text.c
player_gui.c
roadveh_gui.c
settings_gui.c
ship_gui.c
station_gui.c
string.c
string.h
town_gui.c
train_gui.c
win32.c
window.h
--- a/aircraft_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/aircraft_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -202,7 +202,7 @@
 			if (sel_eng != INVALID_ENGINE) {
 				WP(w,buildtrain_d).rename_engine = sel_eng;
 				ShowQueryString(GetCustomEngineName(sel_eng),
-					STR_A039_RENAME_AIRCRAFT_TYPE, 31, 160, w->window_class, w->window_number);
+					STR_A039_RENAME_AIRCRAFT_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			}
 		} break;
 		}
@@ -437,7 +437,7 @@
 		case 2: /* rename */
 			v = GetVehicle(w->window_number);
 			SetDParam(0, v->unitnumber);
-			ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number);
+			ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			break;
 		case 5: /* increase int */
 			mod = _ctrl_pressed? 5 : 10;
--- a/console.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/console.c	Sat Aug 19 09:31:22 2006 +0000
@@ -181,7 +181,7 @@
 					}
 					break;
 				default:
-					if (IsValidAsciiChar(e->keypress.ascii)) {
+					if (IsValidAsciiChar(e->keypress.ascii, CS_ALPHANUMERAL)) {
 						_iconsole_scroll = ICON_BUFFER;
 						InsertTextBufferChar(&_iconsole_cmdline, e->keypress.ascii);
 						IConsoleResetHistoryPos();
@@ -1056,7 +1056,7 @@
 	if (cmdstr[0] == '#') return; // comments
 
 	for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) {
-		if (!IsValidAsciiChar(*cmdptr)) {
+		if (!IsValidAsciiChar(*cmdptr, CS_ALPHANUMERAL)) {
 			IConsoleError("command contains malformed characters, aborting");
 			IConsolePrintF(_icolour_err, "ERROR: command was: '%s'", cmdstr);
 			return;
--- a/gui.h	Sat Aug 19 09:23:48 2006 +0000
+++ b/gui.h	Sat Aug 19 09:31:22 2006 +0000
@@ -5,6 +5,7 @@
 
 #include "station.h"
 #include "window.h"
+#include "string.h"
 
 /* main_gui.c */
 void SetupColorsAndInitialWindow(void);
@@ -106,7 +107,7 @@
 
 void DrawEditBox(Window *w, querystr_d *string, int wid);
 void HandleEditBox(Window *w, querystr_d *string, int wid);
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we);
+int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we, CharSetFilter afilter);
 bool HandleCaret(Textbuf *tb);
 
 void DeleteTextBufferAll(Textbuf *tb);
@@ -136,7 +137,7 @@
 
 bool DoZoomInOutWindow(int how, Window *w);
 void ShowBuildIndustryWindow(void);
-void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number);
+void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number, CharSetFilter afilter);
 void ShowMusicWindow(void);
 
 /* main_gui.c */
--- a/industry_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/industry_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -381,7 +381,7 @@
 					ShowQueryString(STR_CONFIG_PATCHES_INT32,
 							STR_CONFIG_GAME_PRODUCTION,
 							10, 100, w->window_class,
-							w->window_number);
+							w->window_number, CS_ALPHANUMERAL);
 				}
 			}
 		} break;
--- a/main_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/main_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -329,21 +329,21 @@
 {
 	_rename_id = player;
 	_rename_what = 3;
-	ShowQueryString(STR_EMPTY, STR_NETWORK_GIVE_MONEY_CAPTION, 30, 180, 1, 0);
+	ShowQueryString(STR_EMPTY, STR_NETWORK_GIVE_MONEY_CAPTION, 30, 180, 1, 0, CS_NUMERAL);
 }
 
 void ShowNetworkNeedGamePassword(void)
 {
 	_rename_id = NETWORK_GAME_PASSWORD;
 	_rename_what = 4;
-	ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_GAME_PASSWORD_CAPTION, 20, 180, WC_SELECT_GAME, 0);
+	ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_GAME_PASSWORD_CAPTION, 20, 180, WC_SELECT_GAME, 0, CS_ALPHANUMERAL);
 }
 
 void ShowNetworkNeedCompanyPassword(void)
 {
 	_rename_id = NETWORK_COMPANY_PASSWORD;
 	_rename_what = 4;
-	ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, 20, 180, WC_SELECT_GAME, 0);
+	ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, 20, 180, WC_SELECT_GAME, 0, CS_ALPHANUMERAL);
 }
 
 #endif /* ENABLE_NETWORK */
@@ -352,7 +352,7 @@
 {
 	_rename_id = ss->index;
 	_rename_what = 0;
-	ShowQueryString(ss->str, STR_280B_EDIT_SIGN_TEXT, 30, 180, 1, 0);
+	ShowQueryString(ss->str, STR_280B_EDIT_SIGN_TEXT, 30, 180, 1, 0, CS_ALPHANUMERAL);
 }
 
 void ShowRenameWaypointWindow(const Waypoint *wp)
@@ -369,7 +369,7 @@
 	_rename_id = id;
 	_rename_what = 1;
 	SetDParam(0, id);
-	ShowQueryString(STR_WAYPOINT_RAW, STR_EDIT_WAYPOINT_NAME, 30, 180, 1, 0);
+	ShowQueryString(STR_WAYPOINT_RAW, STR_EDIT_WAYPOINT_NAME, 30, 180, 1, 0, CS_ALPHANUMERAL);
 }
 
 static void SelectSignTool(void)
--- a/misc_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/misc_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -897,7 +897,7 @@
 	tb->caretxoffs = tb->width;
 }
 
-int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we)
+int HandleEditBoxKey(Window *w, querystr_d *string, int wid, WindowEvent *we, CharSetFilter afilter)
 {
 	we->keypress.cont = false;
 
@@ -921,11 +921,11 @@
 			InvalidateWidget(w, wid);
 		break;
 	default:
-		if (IsValidAsciiChar(we->keypress.ascii)) {
+		if (IsValidAsciiChar(we->keypress.ascii, afilter)) {
 			if (InsertTextBufferChar(&string->text, we->keypress.ascii))
 				InvalidateWidget(w, wid);
-		} else { // key wasn't caught
-			we->keypress.cont = true;
+		} else { // key wasn't caught. Continue only if standard entry specified
+			we->keypress.cont = (afilter == CS_ALPHANUMERAL);
 		}
 	}
 
@@ -1015,7 +1015,7 @@
 	} break;
 
 	case WE_KEYPRESS: {
-		switch (HandleEditBoxKey(w, &WP(w, querystr_d), 5, e)) {
+		switch (HandleEditBoxKey(w, &WP(w, querystr_d), 5, e, WP(w, querystr_d).afilter)) {
 		case 1: // Return
 			goto press_ok;
 		case 2: // Escape
@@ -1060,7 +1060,7 @@
 static char _edit_str_buf[64];
 static char _orig_str_buf[lengthof(_edit_str_buf)];
 
-void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number)
+void ShowQueryString(StringID str, StringID caption, uint maxlen, uint maxwidth, WindowClass window_class, WindowNumber window_number, CharSetFilter afilter)
 {
 	Window *w;
 	uint realmaxlen = maxlen & ~0x1000;
@@ -1090,6 +1090,7 @@
 	WP(w, querystr_d).text.maxlength = realmaxlen;
 	WP(w, querystr_d).text.maxwidth = maxwidth;
 	WP(w, querystr_d).text.buf = _edit_str_buf;
+	WP(w, querystr_d).afilter = afilter;
 	UpdateTextBufferSize(&WP(w, querystr_d).text);
 }
 
@@ -1358,7 +1359,7 @@
 		}
 
 		if (_saveload_mode == SLD_SAVE_GAME || _saveload_mode == SLD_SAVE_SCENARIO) {
-			if (HandleEditBoxKey(w, &WP(w, querystr_d), 10, e) == 1) /* Press Enter */
+			if (HandleEditBoxKey(w, &WP(w, querystr_d), 10, e, CS_ALPHANUMERAL) == 1) /* Press Enter */
 					HandleButtonClick(w, 12);
 		}
 		break;
--- a/network_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/network_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -24,6 +24,7 @@
 #include "variables.h"
 #include "network_server.h"
 #include "network_udp.h"
+#include "string.h"
 
 #define BGC 5
 #define BTC 15
@@ -430,7 +431,7 @@
 				31 | 0x1000,  // maximum number of characters OR
 				250, // characters up to this width pixels, whichever is satisfied first
 				w->window_class,
-				w->window_number);
+				w->window_number, CS_ALPHANUMERAL);
 		} break;
 		case 13: /* Start server */
 			ShowNetworkStartServerWindow();
@@ -480,7 +481,7 @@
 			break;
 		}
 
-		if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
+		if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e, CS_ALPHANUMERAL) == 1) break; // enter pressed
 
 		// The name is only allowed when it starts with a letter!
 		if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
@@ -651,7 +652,7 @@
 
 		case 4: /* Set password button */
 			ShowQueryString(BindCString(_network_server_password),
-				STR_NETWORK_SET_PASSWORD, 20, 250, w->window_class, w->window_number);
+				STR_NETWORK_SET_PASSWORD, 20, 250, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			break;
 
 		case 5: { /* Select map */
@@ -723,7 +724,7 @@
 
 	case WE_KEYPRESS:
 		if (nd->field == 3) {
-			if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
+			if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e, CS_ALPHANUMERAL) == 1) break; // enter pressed
 
 			ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
 			UpdateTextBufferSize(&WP(w, network_ql_d).q.text);
@@ -1514,7 +1515,7 @@
 		break;
 
 	case WE_KEYPRESS:
-		switch (HandleEditBoxKey(w, &WP(w, querystr_d), 1, e)) {
+		switch (HandleEditBoxKey(w, &WP(w, querystr_d), 1, e, CS_ALPHANUMERAL)) {
 			case 1: /* Return */ SendChat(WP(w, querystr_d).text.buf); /* FALLTHROUGH */
 			case 2: /* Escape */ DeleteWindow(w); break;
 		}
--- a/newgrf_text.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/newgrf_text.c	Sat Aug 19 09:31:22 2006 +0000
@@ -164,7 +164,7 @@
 			case 0x98: *c = 31; break;
 			default:
 				/* Validate any unhandled character */
-				if (!IsValidAsciiChar(*c)) *c = '?';
+				if (!IsValidAsciiChar(*c, CS_ALPHANUMERAL)) *c = '?';
 				break;
 		}
 	}
--- a/player_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/player_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -581,14 +581,14 @@
 			const Player *p = GetPlayer(w->window_number);
 			WP(w, def_d).byte_1 = 0;
 			SetDParam(0, p->president_name_2);
-			ShowQueryString(p->president_name_1, STR_700B_PRESIDENT_S_NAME, 31, 94, w->window_class, w->window_number);
+			ShowQueryString(p->president_name_1, STR_700B_PRESIDENT_S_NAME, 31, 94, w->window_class, w->window_number, CS_ALPHANUMERAL);
 		} break;
 
 		case 6: {/* change company name */
 			Player *p = GetPlayer(w->window_number);
 			WP(w,def_d).byte_1 = 1;
 			SetDParam(0, p->name_2);
-			ShowQueryString(p->name_1, STR_700A_COMPANY_NAME, 31, 150, w->window_class, w->window_number);
+			ShowQueryString(p->name_1, STR_700A_COMPANY_NAME, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
 		} break;
 
 		case 7: {/* build hq */
@@ -619,7 +619,7 @@
 			if (!IsWindowOfPrototype(w, _other_player_company_widgets)) {
 				WP(w,def_d).byte_1 = 2;
 				ShowQueryString(BindCString(_network_player_info[_local_player].password),
-					STR_SET_COMPANY_PASSWORD, sizeof(_network_player_info[_local_player].password), 250, w->window_class, w->window_number);
+					STR_SET_COMPANY_PASSWORD, sizeof(_network_player_info[_local_player].password), 250, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			}
 			#endif
 		}	break;
--- a/roadveh_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/roadveh_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -241,7 +241,7 @@
 		case 2: /* rename */
 			v = GetVehicle(w->window_number);
 			SetDParam(0, v->unitnumber);
-			ShowQueryString(v->string_id, STR_902C_NAME_ROAD_VEHICLE, 31, 150, w->window_class, w->window_number);
+			ShowQueryString(v->string_id, STR_902C_NAME_ROAD_VEHICLE, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			break;
 
 		case 5: /* increase int */
@@ -555,7 +555,7 @@
 			if (sel_eng != INVALID_ENGINE) {
 				WP(w,buildtrain_d).rename_engine = sel_eng;
 				ShowQueryString(GetCustomEngineName(sel_eng),
-					STR_9036_RENAME_ROAD_VEHICLE_TYPE, 31, 160, w->window_class, w->window_number);
+					STR_9036_RENAME_ROAD_VEHICLE_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			}
 		}	break;
 		}
--- a/settings_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/settings_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -840,7 +840,7 @@
 
 					WP(w,def_d).data_3 = btn;
 					SetDParam(0, value);
-					ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_PATCHES_QUERY_CAPT, 10, 100, WC_GAME_OPTIONS, 0);
+					ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_CONFIG_PATCHES_QUERY_CAPT, 10, 100, WC_GAME_OPTIONS, 0, CS_NUMERAL);
 				}
 			}
 
@@ -1138,6 +1138,7 @@
 		int len = 0;
 		int x = e->click.pt.x;
 		StringID str = 0;
+		CharSetFilter afilter = CS_ALPHANUMERAL;
 
 		switch ( line ) {
 			case 0: // rate
@@ -1154,6 +1155,7 @@
 					str = STR_CONFIG_PATCHES_INT32;
 					len = 4;
 					edittext = true;
+					afilter = CS_NUMERAL;
 				}
 			break;
 			case 1: // separator
@@ -1193,6 +1195,7 @@
 					str = STR_CONFIG_PATCHES_INT32;
 					len = 4;
 					edittext = true;
+					afilter = CS_NUMERAL;
 				}
 			break;
 		}
@@ -1205,7 +1208,7 @@
 			len + 1, // maximum number of characters OR
 			250, // characters up to this width pixels, whichever is satisfied first
 			w->window_class,
-			w->window_number);
+			w->window_number, afilter);
 		}
 
 		w->flags4 |= 5 << WF_TIMEOUT_SHL;
--- a/ship_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/ship_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -238,7 +238,7 @@
 		case 2: /* rename */
 			v = GetVehicle(w->window_number);
 			SetDParam(0, v->unitnumber);
-			ShowQueryString(v->string_id, STR_9831_NAME_SHIP, 31, 150, w->window_class, w->window_number);
+			ShowQueryString(v->string_id, STR_9831_NAME_SHIP, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			break;
 		case 5: /* increase int */
 			mod = _ctrl_pressed? 5 : 10;
@@ -388,7 +388,7 @@
 			if (sel_eng != INVALID_ENGINE) {
 				WP(w,buildtrain_d).rename_engine = sel_eng;
 				ShowQueryString(GetCustomEngineName(sel_eng),
-					STR_9838_RENAME_SHIP_TYPE, 31, 160, w->window_class, w->window_number);
+					STR_9838_RENAME_SHIP_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			}
 		}	break;
 		}
--- a/station_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/station_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -675,7 +675,7 @@
 
 		case 9: {
 			SetDParam(0, w->window_number);
-			ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number);
+			ShowQueryString(STR_STATION, STR_3030_RENAME_STATION_LOADING, 31, 180, w->window_class, w->window_number, CS_ALPHANUMERAL);
 		} break;
 
 		case 10: { /* Show a list of scheduled trains to this station */
--- a/string.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/string.c	Sat Aug 19 09:31:22 2006 +0000
@@ -62,10 +62,38 @@
 void str_validate(char *str)
 {
 	for (; *str != '\0'; str++)
-		if (!IsValidAsciiChar(*str)) *str = '?';
+		if (!IsValidAsciiChar(*str, CS_ALPHANUMERAL)) *str = '?';
 }
 
 void strtolower(char *str)
 {
 	for (; *str != '\0'; str++) *str = tolower(*str);
 }
+
+/** Only allow valid ascii-function codes. Filter special codes like BELL and
+ * so on [we need a special filter here later]
+ * @param key character to be checked
+ * @return true or false depending if the character is printable/valid or not */
+bool IsValidAsciiChar(byte key, CharSetFilter afilter)
+{
+	// XXX This filter stops certain crashes, but may be too restrictive.
+	bool firsttest = false;
+
+	switch (afilter) {
+		case CS_ALPHANUMERAL:
+			firsttest = (key >= ' ' && key < 127);
+			break;
+
+		case CS_NUMERAL://we are quite strict, here
+			return (key >= 48 && key <= 57);
+
+		case CS_ALPHA:
+		default:
+			firsttest = ((key >= 'A' && key <= 'Z') || (key >= 'a' && key <= 'z'));
+			break;
+	}
+
+	return (firsttest || (key >= 160 &&
+		key != 0xAA && key != 0xAC && key != 0xAD && key != 0xAF &&
+		key != 0xB5 && key != 0xB6 && key != 0xB7 && key != 0xB9));
+}
--- a/string.h	Sat Aug 19 09:23:48 2006 +0000
+++ b/string.h	Sat Aug 19 09:31:22 2006 +0000
@@ -32,16 +32,16 @@
 /** Convert the given string to lowercase */
 void strtolower(char *str);
 
+typedef enum CharSetFilter {  //valid char filtering
+	CS_ALPHANUMERAL,   //both numeric and alphabetic
+	CS_NUMERAL,        //only numeric ones.
+	CS_ALPHA,          //only alphabetic values
+} CharSetFilter;
+
 /** Only allow valid ascii-function codes. Filter special codes like BELL and
  * so on [we need a special filter here later]
  * @param key character to be checked
  * @return true or false depending if the character is printable/valid or not */
-static inline bool IsValidAsciiChar(byte key)
-{
-	// XXX This filter stops certain crashes, but may be too restrictive.
-	return (key >= ' ' && key < 127) || (key >= 160 &&
-		key != 0xAA && key != 0xAC && key != 0xAD && key != 0xAF &&
-		key != 0xB5 && key != 0xB6 && key != 0xB7 && key != 0xB9);
-}
+bool IsValidAsciiChar(byte key, CharSetFilter afilter);
 
 #endif /* STRING_H */
--- a/town_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/town_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -266,7 +266,7 @@
 
 			case 8: /* rename */
 				SetDParam(0, w->window_number);
-				ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, w->window_class, w->window_number);
+				ShowQueryString(STR_TOWN, STR_2007_RENAME_TOWN, 31, 130, w->window_class, w->window_number, CS_ALPHANUMERAL);
 				break;
 
 			case 9: /* expand town */
--- a/train_gui.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/train_gui.c	Sat Aug 19 09:31:22 2006 +0000
@@ -277,7 +277,7 @@
 			if (sel_eng != INVALID_ENGINE) {
 				WP(w,buildtrain_d).rename_engine = sel_eng;
 				ShowQueryString(GetCustomEngineName(sel_eng),
-					STR_886A_RENAME_TRAIN_VEHICLE_TYPE, 31, 160, w->window_class, w->window_number);
+					STR_886A_RENAME_TRAIN_VEHICLE_TYPE, 31, 160, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			}
 		} break;
 		}
@@ -1269,7 +1269,7 @@
 		case 2: /* name train */
 			v = GetVehicle(w->window_number);
 			SetDParam(0, v->unitnumber);
-			ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number);
+			ShowQueryString(v->string_id, STR_8865_NAME_TRAIN, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
 			break;
 		case 6:	/* inc serv interval */
 			mod = _ctrl_pressed? 5 : 10;
--- a/win32.c	Sat Aug 19 09:23:48 2006 +0000
+++ b/win32.c	Sat Aug 19 09:31:22 2006 +0000
@@ -956,7 +956,7 @@
 		data = GlobalLock(cbuf); // clipboard data
 		dataptr = data;
 
-		for (; IsValidAsciiChar(*dataptr) && (tb->length + length) < (tb->maxlength - 1) &&
+		for (; IsValidAsciiChar(*dataptr, CS_ALPHANUMERAL) && (tb->length + length) < (tb->maxlength - 1) &&
 				(tb->maxwidth == 0 || width + tb->width + GetCharacterWidth(FS_NORMAL, (byte)*dataptr) <= tb->maxwidth); dataptr++) {
 					width += GetCharacterWidth(FS_NORMAL, (byte)*dataptr);
 			length++;
--- a/window.h	Sat Aug 19 09:23:48 2006 +0000
+++ b/window.h	Sat Aug 19 09:31:22 2006 +0000
@@ -3,6 +3,8 @@
 #ifndef WINDOW_H
 #define WINDOW_H
 
+#include "string.h"
+
 typedef union WindowEvent WindowEvent;
 
 typedef void WindowProc(Window *w, WindowEvent *e);
@@ -244,19 +246,11 @@
 	uint16 caretxoffs;          /* the current position of the caret in pixels */
 } Textbuf;
 
-typedef struct querystr_d {
-	StringID caption;
-	WindowClass wnd_class;
-	WindowNumber wnd_num;
-	Textbuf text;
-	const char *orig;
-} querystr_d;
-
 #define WP(ptr,str) (*(str*)(ptr)->custom)
 /* You cannot 100% reliably calculate the biggest custom struct as
  * the number of pointers in it and alignment will have a huge impact.
- * 88 is the largest window-size for 64-bit machines currently */
-#define WINDOW_CUSTOM_SIZE 88
+ * 96 is the largest window-size for 64-bit machines currently */
+#define WINDOW_CUSTOM_SIZE 96
 
 typedef struct Scrollbar {
 	uint16 count, cap, pos;
@@ -300,6 +294,16 @@
 	byte custom[WINDOW_CUSTOM_SIZE];
 };
 
+typedef struct querystr_d {
+	StringID caption;
+	WindowClass wnd_class;
+	WindowNumber wnd_num;
+	Textbuf text;
+	const char *orig;
+	CharSetFilter afilter;
+} querystr_d;
+assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(querystr_d));
+
 typedef struct {
 	byte item_count;      /* follow_vehicle */
 	byte sel_index;       /* scrollpos_x */