Skip to content

Commit

Permalink
Output text formatting, call free(), etc.
Browse files Browse the repository at this point in the history
  • Loading branch information
eakondratiev committed Feb 6, 2021
1 parent 584af76 commit 8d4b81e
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 95 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.git/
misc-files/
186 changes: 123 additions & 63 deletions ReadCrd.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
/*
* ReadCrd - reading Windows CRD files.
*
* MIT License
*
* Copyright (c) 2021 E. Kondratiev (https://github.com/eakondratiev/)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <malloc.h>
#include <stdio.h>
#include <string.h>
Expand All @@ -15,9 +40,9 @@ int main (int argc, char** argv) {

enc = ASCII;

// excepcted argments:
// ReadCrd filename
// ReadCrd -e Windows-1251 filename
/* excepcted argments: */
/* ReadCrd filename */
/* ReadCrd -e Windows-1251 filename */
if (argc != 2 && argc != 4) {

Usage (argv[0]);
Expand All @@ -34,7 +59,7 @@ int main (int argc, char** argv) {
}
}

filename = argv[argc - 1]; // last argument
filename = argv[argc - 1]; /* last argument */
printf ("\nRead Windows Card MGC/RRG File %s", filename);

switch (ReadFile (filename, enc)) {
Expand All @@ -45,7 +70,7 @@ int main (int argc, char** argv) {
printf ("\nNot card file.\n\n");
break;
case 0:
printf ("\nDone.\n\n");
printf ("\n\n");
break;
}

Expand All @@ -60,17 +85,17 @@ void Usage (char *filePath) {
char* fileName;
char* slashPtr;

// Get the program name.
// On Linux and Windows the filePath can contain othe folders,
// so we get the program name as characters after the last slash.
slashPtr = strrchr(filePath, '/'); // the last slash on Linux
/* Get the program name. */
/* On Linux and Windows the filePath can contain othe folders, */
/* so we get the program name as characters after the last slash. */
slashPtr = strrchr(filePath, '/'); /* the last slash on Linux */

if (slashPtr) {
fileName = slashPtr + 1;
}
else {

slashPtr = strrchr(filePath, '\\'); // the last slash on Windows
slashPtr = strrchr(filePath, '\\'); /* the last slash on Windows */

if (slashPtr) {
fileName = slashPtr + 1;
Expand Down Expand Up @@ -106,7 +131,7 @@ int ReadFile (char* filename, enum SourceFileEncoding encoding) {
int *cardOffsets;
int i;

f = fopen(filename, "rb"); // read, binary
f = fopen(filename, "rb"); /* read, binary */

if (!f) {
return -1; // Not opened
Expand All @@ -124,8 +149,7 @@ int ReadFile (char* filename, enum SourceFileEncoding encoding) {
totalCards = *(short *)rrgHeader.totalCards;
fileType = RRG;

printf ("\n\nRRG card file, id %i, cards %i\n",
*(int *)rrgHeader.lastObjectId, totalCards);
printf ("\n\nRRG card file, total cards: %i\n", totalCards);

}
else if (cfs.letter[0] == 'M' &&
Expand All @@ -137,7 +161,7 @@ int ReadFile (char* filename, enum SourceFileEncoding encoding) {
totalCards = *(short *)mgcHeader.totalCards;
fileType = MGC;

printf ("\n\nMGC card file, cards %i\n", totalCards);
printf ("\n\nMGC card file, total cards: %i\n", totalCards);

}
else {
Expand All @@ -154,6 +178,8 @@ int ReadFile (char* filename, enum SourceFileEncoding encoding) {
ReadCardIndex (f, encoding, cardOffsets, i);
ReadCard (f, encoding, fileType, cardOffsets [i]);
}

free (cardOffsets);
}

fclose (f);
Expand All @@ -167,22 +193,43 @@ int ReadCardIndex (FILE* f, enum SourceFileEncoding encoding, int* cardOffsets,

size_t indexSize = sizeof (struct CardIndex);
struct CardIndex ci;
char* text;

fread (&ci, indexSize, 1, f);

if (*(int *)ci.absolutePosition == 0 ||
ci.flag != 0) {

// Empty card or the flag is not zero
/* Empty card or the flag is not zero */
cardOffsets[cardIndex] = -1;
return -1;
}

cardOffsets[cardIndex] = *(int *)ci.absolutePosition;
text = getText (ci.indexLineText, encoding);

/* Left space padding to align the card number. */
char* spaces = " ";
int padLength;

if (cardIndex < 9) {
padLength = 2; /* printed number 1...9 */
}
else if (cardIndex < 99) {
padLength = 1; /* printed number 10...99 */
}
else {
padLength = 0;
}

printf ("\nCard %i", cardIndex + 1);
printf ("\n-------");
printf ("\n%s\n", getText (ci.indexLineText, encoding));
/* format specification: %[flags][width][.precision][size]type */
printf ("\n%.*sCard %i", padLength, spaces, cardIndex + 1);
printf ("\n--------");
printf ("\n%s\n", text);

if (text != ci.indexLineText) {
free (text); /* it was allocated in getText */
}

return 0;
}
Expand All @@ -195,17 +242,18 @@ int ReadCard (FILE* f, enum SourceFileEncoding encoding, enum CardFileType fileT
unsigned short bitmapLength;
unsigned short textLength;
fpos_t prevPosition;
char* text;
char* text = NULL;
char* utf8text;

if (cardOffset < 0) {
return -1;
}

// Save the current read position
/* Save the current read position */
fgetpos (f, &prevPosition);

// Set the file position of the stream:
// move to the place from the file beginning.
/* Set the file position of the stream: */
/* move to the place from the file beginning. */
fseek (f, cardOffset, SEEK_SET);

// format source: http://cardwin.sourceforge.net/
Expand All @@ -218,33 +266,32 @@ int ReadCard (FILE* f, enum SourceFileEncoding encoding, enum CardFileType fileT
if (bitmapLength == 0) {
// No object
fread (&textLength, sizeof(unsigned short), 1, f);

// read the text
textLength += 3; // by specification
text = calloc (textLength + 1, sizeof (char));
text [textLength] = '\0'; // terminate the string
fread (text, sizeof(char), textLength, f);

printf ("\n%s\n", getText (text, encoding));
}
else {
// bytes
// 2 - 5 UID
// 6 - x OLE object
// x+1 - x+2 DIB character width
// x+3 - x+4 DIB character height
// x+5 - x+6 X coordinate U-L
// x+7 - x+8 Y coordinate U-L
// x+9 - x+10 X coordinate L-R
// x+11 - x+12 Y coordinate L-R
// x+13 - x+14 embedded=0,linked=1, static=2
// x+15 - x+16 length of text entry
// x+17 - y text
// WHERE:
// x = 6 + size in bytes of OLE object.
// y = x + 16 + text entry length

// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-oleds/5a95d153-a771-4408-8041-ae87c45b6987
/* bytes
* 2 - 5 UID
* 6 - x OLE object
* x+1 - x+2 DIB character width
* x+3 - x+4 DIB character height
* x+5 - x+6 X coordinate U-L
* x+7 - x+8 Y coordinate U-L
* x+9 - x+10 X coordinate L-R
* x+11 - x+12 Y coordinate L-R
* x+13 - x+14 embedded=0,linked=1, static=2
* x+15 - x+16 length of text entry
* x+17 - y text
* WHERE:
* x = 6 + size in bytes of OLE object.
* y = x + 16 + text entry length
* https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-oleds/5a95d153-a771-4408-8041-ae87c45b6987
*/
unsigned int uid; // 4 bytes
unsigned int OLEversion;
unsigned int formatID;
Expand All @@ -268,25 +315,37 @@ int ReadCard (FILE* f, enum SourceFileEncoding encoding, enum CardFileType fileT

// read the lext length
if (bitmapLength > 0) {
fseek (f, 10 + bitmapLength, SEEK_CUR);
fseek (f, 10 + bitmapLength, SEEK_CUR);
}
fread (&textLength, sizeof(unsigned short), 1, f);

// read the text
text = calloc (textLength + 1, sizeof (char));
text [textLength] = '\0'; // terminate the string
fread (text, sizeof(char), textLength, f);

printf ("\n%s\n", getText (text, encoding));
break;

default:
printf ("\nWrong file type.\n");
}

//printf ("\nType: %i, OFFSET: %x\n", fileType, cardOffset);
if (text) {
// the text was allocated and read
// optionally convert to UTF-8
utf8text = getText (text, encoding); // either text or newly allocated string

printf ("\n%s\n", utf8text);

if (text != utf8text) {
// free converter text
free (utf8text);
}
// free read text
free (text);
}

// Restore reading position
/* Restore reading position */
fsetpos (f, &prevPosition);

return 0;
Expand All @@ -302,14 +361,14 @@ char* getText (char* text, enum SourceFileEncoding encoding) {
return win1251toUtf8(text);

default:
// As is, ASCII
/* As is, ASCII */
return text;
}

}

/**
* Returns new string with Windows-1251 characters (byte)
* Returns the new string with Windows-1251 characters (byte)
* converted to UTF-8 characters (two bytes).
*/
char* win1251toUtf8 (char* src) {
Expand All @@ -325,33 +384,34 @@ char* win1251toUtf8 (char* src) {
resPtr = res;
memset (res, 0, sizeof(res));

// W1251 UTF8 two bytes representation
// ----- ---- ---------------------------
// А c0 d090 -48 (d0) -112 (90) \220
// Б c1 d091 -111 (91) \221
// Я df d0af -81 (af) \257
// а e0 d0b0 -80 (b0)
// п ef d0bf -65 (bf)
// р f0 d180 -47 (d1) -128 (80)
// с f1 d181 -127 (81)
// я ff d18f -113 (8f)
// NOTE: -48 dec = d0 hex
/* W1251 UTF8 two bytes representation
* ----- ---- ---------------------------
* А c0 d090 -48 (d0) -112 (90) \220
* Б c1 d091 -111 (91) \221
* Я df d0af -81 (af) \257
* а e0 d0b0 -80 (b0)
* п ef d0bf -65 (bf)
* р f0 d180 -47 (d1) -128 (80)
* с f1 d181 -127 (81)
* я ff d18f -113 (8f)
* NOTE: -48 dec = d0 hex
*/

while (*src != '\0') {

c = (unsigned char)*src;

if (0xC0 <= c && c <= 0xEF) {
// Convert, one char will be two chars
// А c0 -> {d0, 90} ... п ef -> {d0, bf}
/* Convert, one char will be two chars */
/* А c0 -> {d0, 90} ... п ef -> {d0, bf} */
resPtr[0] = 0xd0;
resPtr[1] = 0x90 + c - 0xc0; // UTF-8 Cyr A + c - Win1251 Cyr A
resPtr += 2;
counter += 2;
}
else if (0xF0 <= c && c <= 0xFF) {
// Convert, one char will be two chars
// р f0 -> {d1, 80} ... я ff -> {d1, 8f}
/* Convert, one char will be two chars */
/* р f0 -> {d1, 80} ... я ff -> {d1, 8f} */
resPtr[0] = 0xd1;
resPtr[1] = 0x80 + c - 0xf0; // UTF-8 Cyr р + c - Win1251 Cyr р
resPtr += 2;
Expand Down
Loading

0 comments on commit 8d4b81e

Please sign in to comment.