mirror of
				https://github.com/pbatard/rufus.git
				synced 2024-08-14 23:57:05 +00:00 
			
		
		
		
	[localization] add parser
This commit is contained in:
		
							parent
							
								
									f8c6903d21
								
							
						
					
					
						commit
						011dd93b7a
					
				
					 3 changed files with 256 additions and 2 deletions
				
			
		
							
								
								
									
										250
									
								
								src/parser.c
									
										
									
									
									
								
							
							
						
						
									
										250
									
								
								src/parser.c
									
										
									
									
									
								
							|  | @ -34,6 +34,256 @@ | |||
| #include "rufus.h" | ||||
| #include "msapi_utf8.h" | ||||
| 
 | ||||
| 
 | ||||
| // What we need for localization
 | ||||
| // # Comment
 | ||||
| // v 1 1                    // UI target version (major, minor)
 | ||||
| // p IDD_DIALOG             // parent dialog for the following
 | ||||
| // d 1                      // set text direction 0: left to right, 1 right to left
 | ||||
| // f "MS Dialog" 12         // set font and font size
 | ||||
| // r IDD_DIALOG +30 +30     // resize dialog (delta_w, delta_h)
 | ||||
| // m IDC_START  -10 0       // move control (delta_x, delta_w)
 | ||||
| // r IDC_START  0 +1        // resize control
 | ||||
| // t IDC_START  "Demarrer"  // Change control text
 | ||||
| // t IDC_LONG_CONTROL "Some text here"
 | ||||
| //  "some continued text there"
 | ||||
| // all parsed commands return: cmd, control_id, text, num1, num2
 | ||||
| 
 | ||||
| // TODO: display control name on mouseover
 | ||||
| // Link to http://www.resedit.net/
 | ||||
| 
 | ||||
| typedef struct localization_command { | ||||
| 	int command; | ||||
| 	wchar_t* text1; | ||||
| 	wchar_t* text2; | ||||
| 	int32_t num1; | ||||
| 	int32_t num2; | ||||
| } loc_cmd; | ||||
| 
 | ||||
| int  loc_line_nr = 0; | ||||
| char loc_filename[32]; | ||||
| #define luprintf(msg) uprintf("%s(%d): " msg "\n", loc_filename, loc_line_nr); | ||||
| 
 | ||||
| // Parse localization command arguments and fill a localization command structure
 | ||||
| static void get_loc_data_args(char* arg_type, wchar_t* wline) { | ||||
| 	const wchar_t wspace[] = L" \t"; | ||||
| 	size_t i, r, arg_index; | ||||
| 	char str[1024];	// Fot testing only
 | ||||
| 	long n; | ||||
| 	wchar_t *endptr, *expected_endptr; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 	for (arg_index=0; arg_type[arg_index] != 0; arg_index++) { | ||||
| 		// Skip leading spaces
 | ||||
| 		i += wcsspn(&wline[i], wspace); | ||||
| 		r = i; | ||||
| 		switch(arg_type[arg_index]) { | ||||
| 		case 's':	// quoted string
 | ||||
| 			// search leading quote
 | ||||
| 			if (wline[i++] != L'"') { | ||||
| 				luprintf("missing leading quote"); | ||||
| 				return; | ||||
| 			} | ||||
| 			r = i; | ||||
| 			// locate ending quote
 | ||||
| 			while ((wline[i] != 0) && (wline[i] != L'"') || ((wline[i] == L'"') && (wline[i-1] == L'\\'))) { | ||||
| 				if ((wline[i] == L'"') && (wline[i-1] == L'\\')) { | ||||
| 					wcscpy_s(&wline[i-1], i+wcslen(&wline[i]), &wline[i]); | ||||
| 				} else { | ||||
| 					i++; | ||||
| 				} | ||||
| 			} | ||||
| 			if (wline[i] == 0) { | ||||
| 				luprintf("missing ending quote"); | ||||
| 				return; | ||||
| 			} | ||||
| 			wline[i++] = 0; | ||||
| 			wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str)); | ||||
| 			uprintf("Got string: '%s'\n", str); | ||||
| 			break; | ||||
| 		case 'w':	// single word
 | ||||
| 			while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1])) | ||||
| 				i++; | ||||
| 			if (wline[i] != 0) | ||||
| 				wline[i++] = 0; | ||||
| 			wchar_to_utf8_no_alloc(&wline[r], str, sizeof(str)); | ||||
| 			uprintf("Got word: %s\n", str); | ||||
| 			break; | ||||
| 		case 'i':	// integer
 | ||||
| 			while ((wline[i] != 0) && (wline[i] != wspace[0]) && (wline[i] != wspace[1])) | ||||
| 				i++; | ||||
| 			expected_endptr = &wline[i]; | ||||
| 			if (wline[i] != 0) | ||||
| 				wline[i++] = 0; | ||||
| 			n = wcstol(&wline[r], &endptr, 10); | ||||
| 			if (endptr != expected_endptr) { | ||||
| 				luprintf("could not read integer data"); | ||||
| 				return; | ||||
| 			} else { | ||||
| 				uprintf("Got integer: %d\n", n); | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			uprintf("localization: unhandled arg_type '%c'\n", arg_type[arg_index]); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // Parse an UTF-16 localization command line
 | ||||
| static void* get_loc_data_line(wchar_t* wline) | ||||
| { | ||||
| 	const wchar_t wspace[] = L" \t"; | ||||
| 	size_t i; | ||||
| 	wchar_t t; | ||||
| 	BOOLEAN quoteth = FALSE; | ||||
| 	char line[8192]; | ||||
| 
 | ||||
| 	if ((wline == NULL) || (wline[0] == 0)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	i = 0; | ||||
| 
 | ||||
| 	// Skip leading spaces
 | ||||
| 	i += wcsspn(&wline[i], wspace); | ||||
| 
 | ||||
| 	// Read token (NUL character will be read if EOL)
 | ||||
| 	t = wline[i++]; | ||||
| 	switch (t) { | ||||
| 	case 't': | ||||
| 		get_loc_data_args("ws", &wline[i]); | ||||
| 		return NULL; | ||||
| 	case 'f': | ||||
| 		get_loc_data_args("si", &wline[i]); | ||||
| 		return NULL; | ||||
| 	case 'r': | ||||
| 	case 'm': | ||||
| 		get_loc_data_args("wii", &wline[i]); | ||||
| 		return NULL; | ||||
| 	case 'v': | ||||
| 		get_loc_data_args("ii", &wline[i]); | ||||
| 		return NULL; | ||||
| 	case '#':	// comment
 | ||||
| 		return NULL; | ||||
| 	default: | ||||
| 		wchar_to_utf8_no_alloc(wline, line, sizeof(line)); | ||||
| 		luprintf("syntax error"); | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static __inline void *_reallocf(void *ptr, size_t size) | ||||
| { | ||||
| 	void *ret = realloc(ptr, size); | ||||
| 	if (!ret) | ||||
| 		free(ptr); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| // Parse a Rufus localization command file (ANSI, UTF-8 or UTF-16)
 | ||||
| char* get_loc_data_file(const char* filename) | ||||
| { | ||||
| 	wchar_t *wdata= NULL, *wfilename = NULL, *wbuf = NULL; | ||||
| 	size_t wbufsize = 1024;	// size in wchar_t
 | ||||
| 	FILE* fd = NULL; | ||||
| 	char *ret = NULL; | ||||
| 	size_t i = 0; | ||||
| 	int r, line_nr_incr = 1; | ||||
| 	wchar_t wc = 0, last_wc; | ||||
| 	BOOL eol = FALSE; | ||||
| 
 | ||||
| 	if ((filename == NULL) || (filename[0] == 0)) | ||||
| 		return NULL; | ||||
| 
 | ||||
| 	loc_line_nr = 0; | ||||
| 	safe_strcpy(loc_filename, sizeof(loc_filename), filename); | ||||
| 	wfilename = utf8_to_wchar(filename); | ||||
| 	if (wfilename == NULL) { | ||||
| 		uprintf("localization: could not convert '%s' filename to UTF-16\n", filename); | ||||
| 		goto out; | ||||
| 	} | ||||
| 	fd = _wfopen(wfilename, L"r, ccs=UNICODE"); | ||||
| 	if (fd == NULL) goto out; | ||||
| 
 | ||||
| 	wbuf = (wchar_t*) malloc(wbufsize*sizeof(wchar_t)); | ||||
| 	if (wbuf == NULL) { | ||||
| 		uprintf("localization: could not allocate line buffer\n"); | ||||
| 		goto out; | ||||
| 	} | ||||
| 
 | ||||
| 	do {	// custom readline handling for string collation, realloc, line number handling, etc.
 | ||||
| 		last_wc = wc; | ||||
| 		wc = getwc(fd); | ||||
| 		switch(wc) { | ||||
| 		case WEOF: | ||||
| 			wbuf[i] = 0; | ||||
| 			get_loc_data_line(wbuf); | ||||
| 			goto out; | ||||
| 		case 0x0D: | ||||
| 		case 0x0A: | ||||
| 			// Process line numbers
 | ||||
| 			if ((last_wc != 0x0D) && (last_wc != 0x0A)) { | ||||
| 				if (eol) { | ||||
| 					line_nr_incr++; | ||||
| 				} else { | ||||
| 					loc_line_nr += line_nr_incr; | ||||
| 					line_nr_incr = 1; | ||||
| 				} | ||||
| 			} | ||||
| 			wbuf[i] = 0; | ||||
| 			if (!eol) { | ||||
| 				// Strip trailing spaces (for string collation)
 | ||||
| 				for (r = ((int)i)-1; (r>0) && ((wbuf[r]==0x20)||(wbuf[r]==0x09)); r--); | ||||
| 				if (r < 0) | ||||
| 					r = 0; | ||||
| 				eol = TRUE; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 0x20: | ||||
| 		case 0x09: | ||||
| 			if (!eol) { | ||||
| 				wbuf[i++] = wc; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			// Collate multiline strings
 | ||||
| 			if ((eol) && (wc == L'"') && (wbuf[r] == L'"')) { | ||||
| 				i = r; | ||||
| 				eol = FALSE; | ||||
| 				break; | ||||
| 			} | ||||
| 			if (eol) { | ||||
| 				get_loc_data_line(wbuf); | ||||
| 				eol = FALSE; | ||||
| 				i = 0; | ||||
| 				r = 0; | ||||
| 			} | ||||
| 			wbuf[i++] = wc; | ||||
| 			break; | ||||
| 		} | ||||
| 		if (i >= wbufsize-1) { | ||||
| 			wbufsize *= 2; | ||||
| 			if (wbufsize > 32768) { | ||||
| 				uprintf("localization: requested line buffer is larger than 32K!\n"); | ||||
| 				goto out; | ||||
| 			} | ||||
| 			wbuf = (wchar_t*) _reallocf(wbuf, wbufsize*sizeof(wchar_t)); | ||||
| 			if (wbuf == NULL) { | ||||
| 				uprintf("localization: could not grow line buffer\n"); | ||||
| 				goto out; | ||||
| 			} | ||||
| 		} | ||||
| 	} while(1); | ||||
| 
 | ||||
| out: | ||||
| 	if (fd != NULL) | ||||
| 		fclose(fd); | ||||
| 	safe_free(wfilename); | ||||
| 	safe_free(wbuf); | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // Parse a line of UTF-16 text and return the data if it matches the 'token'
 | ||||
| // The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is 
 | ||||
| // modified by the parser
 | ||||
|  |  | |||
|  | @ -1144,7 +1144,7 @@ void ToggleAdvanced(void) | |||
| 	MoveControl(hMainDialog, IDC_LOG, dialog_shift); | ||||
| 	MoveControl(hMainDialog, IDCANCEL, dialog_shift); | ||||
| #ifdef RUFUS_TEST | ||||
| 	MoveControl(hMainDialogm, IDC_TEST, dialog_shift); | ||||
| 	MoveControl(hMainDialog, IDC_TEST, dialog_shift); | ||||
| #endif | ||||
| 
 | ||||
| 	// And do the same for the log dialog while we're at it
 | ||||
|  | @ -1423,6 +1423,9 @@ static void PrintStatus2000(const char* str, BOOL val) | |||
| 	PrintStatus(2000, FALSE, "%s %s.", str, (val)?"enabled":"disabled"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| // TODO: remove me
 | ||||
| extern char* get_loc_data_file(const char* filename); | ||||
| /*
 | ||||
|  * Main dialog callback | ||||
|  */ | ||||
|  | @ -1561,6 +1564,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | |||
| 			break; | ||||
| #ifdef RUFUS_TEST | ||||
| 		case IDC_TEST: | ||||
| 			get_loc_data_file("rufus.loc"); | ||||
| 			break; | ||||
| #endif | ||||
| 		case IDC_ADVANCED: | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ | |||
| /* Program options */ | ||||
| #define RUFUS_DEBUG                 // print debug info to Debug facility
 | ||||
| /* Features not ready for prime time and that may *DESTROY* your data - USE AT YOUR OWN RISKS! */ | ||||
| //#define RUFUS_TEST
 | ||||
| #define RUFUS_TEST | ||||
| 
 | ||||
| #define APPLICATION_NAME            "Rufus" | ||||
| #define COMPANY_NAME                "Akeo Consulting" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue