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 "rufus.h" | ||||||
| #include "msapi_utf8.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'
 | // 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 
 | // The parsed line is of the form: [ ]token[ ]=[ ]["]data["][ ] and is 
 | ||||||
| // modified by the parser
 | // modified by the parser
 | ||||||
|  |  | ||||||
|  | @ -1144,7 +1144,7 @@ void ToggleAdvanced(void) | ||||||
| 	MoveControl(hMainDialog, IDC_LOG, dialog_shift); | 	MoveControl(hMainDialog, IDC_LOG, dialog_shift); | ||||||
| 	MoveControl(hMainDialog, IDCANCEL, dialog_shift); | 	MoveControl(hMainDialog, IDCANCEL, dialog_shift); | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 	MoveControl(hMainDialogm, IDC_TEST, dialog_shift); | 	MoveControl(hMainDialog, IDC_TEST, dialog_shift); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 	// And do the same for the log dialog while we're at it
 | 	// 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"); | 	PrintStatus(2000, FALSE, "%s %s.", str, (val)?"enabled":"disabled"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | // TODO: remove me
 | ||||||
|  | extern char* get_loc_data_file(const char* filename); | ||||||
| /*
 | /*
 | ||||||
|  * Main dialog callback |  * Main dialog callback | ||||||
|  */ |  */ | ||||||
|  | @ -1561,6 +1564,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA | ||||||
| 			break; | 			break; | ||||||
| #ifdef RUFUS_TEST | #ifdef RUFUS_TEST | ||||||
| 		case IDC_TEST: | 		case IDC_TEST: | ||||||
|  | 			get_loc_data_file("rufus.loc"); | ||||||
| 			break; | 			break; | ||||||
| #endif | #endif | ||||||
| 		case IDC_ADVANCED: | 		case IDC_ADVANCED: | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
| /* Program options */ | /* Program options */ | ||||||
| #define RUFUS_DEBUG                 // print debug info to Debug facility
 | #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! */ | /* 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 APPLICATION_NAME            "Rufus" | ||||||
| #define COMPANY_NAME                "Akeo Consulting" | #define COMPANY_NAME                "Akeo Consulting" | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue