/*++ Copyright (c) 1997 Microsoft Corporation Module Name: msgfile.c Abstract: Routines to load and process a text message file. The message file is in the following format: [] text [] text etc. Notes: 1) Lines in the file before the first section are ignored. This is the only mechanism for comments in the file. 2) To be recognized as a section name, the [ must be the first character on the line, and there cannot be any spaces between the [ and the ]. The number must be a decimal number in the range 0 - 65535 inclusive. 3) Trailing space at the end of a line is ignored. 4) Empty lines at the trail end of a message are ignored completely. Empty means a newline only or whitespace and a newline only. 5) The final newline in a message is ignored but internal ones are kept. Thus in the following example, message #3 is the 4 line message "\nThis\nis\n\na\n\nmessage" [3] This is a message [4] Author: Ted Miller (tedm) 20 June 1997 Revision History: --*/ #include #include #include #include #include #include #define MAX_LINE_LEN 100 #define MAX_MSG_LEN 5000 BOOL PatchMessagesFromFile( IN FPCHAR Filename, IN OUT FPMESSAGE_STRING Messages, IN UINT MessageCount ); BOOL ProcessMessage( IN char *msg, IN UINT MsgNumber, IN FPMESSAGE_STRING Messages, IN UINT MessageCount ); BOOL GetTextForProgram( IN FPCHAR Argv0, IN OUT FPMESSAGE_STRING Messages, IN UINT MessageCount ) { char Filename[256]; char *p; strcpy(Filename,Argv0); if(p = strrchr(Filename,'\\')) { p++; } else { p = Filename; } if(p = strchr(p,'.')) { *p = 0; } strcat(p,".msg"); return(PatchMessagesFromFile(Filename,Messages,MessageCount)); } BOOL PatchMessagesFromFile( IN FPCHAR Filename, IN OUT FPMESSAGE_STRING Messages, IN UINT MessageCount ) { FILE *hFile; char line[MAX_LINE_LEN]; char *msg; char *End; UINT MsgNumber; unsigned long l; unsigned u; BOOL Valid; msg = malloc(MAX_MSG_LEN); if(!msg) { return(FALSE); } // // Open the file. // hFile = fopen(Filename,"rt"); if(!hFile) { free(msg); return(FALSE); } MsgNumber = (UINT)(-1); Valid = TRUE; while(Valid && fgets(line,MAX_LINE_LEN,hFile)) { if(line[0] == '[') { // // New message. Terminate the current one and then make sure // the section name specifies a valid number. // if(MsgNumber != (UINT)(-1)) { Valid = ProcessMessage(msg,MsgNumber,Messages,MessageCount); } if(Valid) { l = strtoul(&line[1],&End,10); if((l > 65535L) || (*End != ']')) { Valid = FALSE; } else { MsgNumber = (UINT)l; msg[0] = 0; } } } else { // // Ignore lines in the file before the first section // if(MsgNumber != (UINT)(-1)) { // // Strip out trailing space. Account for the newline that // fgets leaves in the buffer. // u = strlen(line); while(u && ((line[u-1] == ' ') || (line[u-1] == '\t') || (line[u-1] == '\n'))) { u--; } // // Put a newline back at the end of the line. // line[u++] = '\n'; line[u] = 0; if((strlen(msg) + u) < MAX_MSG_LEN) { strcat(msg,line); } } } } // // Check loop termination condition to see whether we read the whole // file correctly. // if(Valid && ferror(hFile)) { Valid = FALSE; } fclose(hFile); // // Process pending messsage if there is one. // if(Valid && (MsgNumber != (UINT)(-1))) { if(!ProcessMessage(msg,MsgNumber,Messages,MessageCount)) { Valid = FALSE; } } free(msg); return(Valid); } BOOL ProcessMessage( IN char *msg, IN UINT MsgNumber, IN FPMESSAGE_STRING Messages, IN UINT MessageCount ) { UINT m; unsigned u; FPVOID p; // // Strip out trailing newline(s). // u = strlen(msg); while(u && (msg[u-1] == '\n')) { msg[--u] = 0; } // // Locate the relevent message in the caller's table. // for(m=0; m strlen(*Messages[m].String))) { p = malloc(u+1); if(!p) { return(FALSE); } if(*Messages[m].String) { free(*Messages[m].String); } *Messages[m].String = p; } strcpy(*Messages[m].String,msg); break; } } return(TRUE); }