269 lines
5.5 KiB
C
269 lines
5.5 KiB
C
|
/*++
|
||
|
|
||
|
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:
|
||
|
|
||
|
[<id>]
|
||
|
text
|
||
|
|
||
|
[<id>]
|
||
|
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 <mytypes.h>
|
||
|
#include <msgfile.h>
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <malloc.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
|
||
|
#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<MessageCount; m++) {
|
||
|
if(Messages[m].Id == MsgNumber) {
|
||
|
|
||
|
//
|
||
|
// If the message fits in place, put it there.
|
||
|
// Otherwise allocate memory and copy it.
|
||
|
//
|
||
|
if(!(*Messages[m].String) || (u > 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);
|
||
|
}
|