1///////////////////////////////////////////////////////////////////////////// 2// Name: readshg.cpp 3// Purpose: Petr Smilauer's .SHG (Segmented Hypergraphics file) reading 4// code. 5// Note: .SHG is undocumented (anywhere!) so this is 6// reverse-engineering 7// and guesswork at its best. 8// Author: Petr Smilauer 9// Modified by: Wlodzimiez ABX Skiba 2003/2004 Unicode support 10// Ron Lee 11// Created: 01/01/99 12// RCS-ID: $Id: readshg.cpp 35650 2005-09-23 12:56:45Z MR $ 13// Copyright: (c) Petr Smilauer 14// Licence: wxWindows licence 15///////////////////////////////////////////////////////////////////////////// 16 17// For compilers that support precompilation, includes "wx.h". 18#include "wx/wxprec.h" 19 20#ifdef __BORLANDC__ 21#pragma hdrstop 22#endif 23 24#ifndef WX_PRECOMP 25#endif 26 27#include <stdio.h> 28#include <stdlib.h> 29 30#include "readshg.h" 31#include "tex2any.h" 32 33// Returns the number of hotspots, and the array of hotspots. 34// E.g. 35// HotSpots *array; 36// int n = ParseSHG("thing.shg", &array); 37 38int ParseSHG( const wxChar* fileName, HotSpot **hotspots) 39{ FILE* fSHG = wxFopen( fileName, _T("rb")); 40 long offset; 41 int nHotspots = 0; 42 43 if(fSHG == 0) 44 return 0; 45 nHotspots = 0; 46 //first, look at offset OFF_OFFSET to get another offset :-) 47 fseek( fSHG, OFF_OFFSET, SEEK_SET); 48 offset = 0L; // init whole 4-byte variable 49 fread( &offset, 2, 1, fSHG); // get the offset in first two bytes.. 50 if(offset == 0) // if zero, used next DWORD field 51 fread( &offset, 4, 1, fSHG);// this is our offset for very long DIB 52 offset += 9; // don't know hot this delta comes-about 53 if(fseek( fSHG, offset, SEEK_SET) != 0) 54 { 55 fclose( fSHG); 56 return -1; // this is probably because incorrect offset calculation. 57 } 58 fread( &nHotspots, 2, 1, fSHG); 59 60 *hotspots = new HotSpot[nHotspots]; 61 62 int nMacroStrings = 0; 63 64 fread( &nMacroStrings, 2, 1, fSHG); // we can ignore the macros, as this is 65 // repeated later, but we need to know how much to skip 66 fseek( fSHG, 2, SEEK_CUR); // skip another 2 bytes I do not understand ;-) 67 68 ShgInfoBlock sib; 69 int i; 70 71 int sizeOf = sizeof( ShgInfoBlock); 72 73 for( i = 0 ; i < nHotspots ; ++i) 74 { 75 fread( &sib, sizeOf, 1, fSHG); // read one hotspot' info 76 // analyse it: 77 (*hotspots)[i].type = (HotspotType)(sib.hotspotType & 0xFB); 78 (*hotspots)[i].left = sib.left; 79 (*hotspots)[i].top = sib.top; 80 (*hotspots)[i].right = sib.left + sib.width; 81 (*hotspots)[i].bottom = sib.top + sib.height; 82 (*hotspots)[i].IsVisible = ((sib.hotspotType & 4) == 0); 83 (*hotspots)[i].szHlpTopic_Macro[0] = '\0'; 84 } 85 // we have it...now read-off the macro-string block 86 if(nMacroStrings > 0) 87 fseek( fSHG, nMacroStrings, SEEK_CUR); //nMacroStrings is byte offset... 88 // and, at the last, read through the strings: hotspot-id[ignored], then topic/macro 89 int c; 90 for( i = 0 ; i < nHotspots ; ++i) 91 { 92 while( (c = fgetc( fSHG)) != 0) 93 ; 94 // now read it: 95 int j = 0; 96 while( (c = fgetc( fSHG)) != 0) 97 { 98 (*hotspots)[i].szHlpTopic_Macro[j] = (wxChar)c; 99 ++j; 100 } 101 (*hotspots)[i].szHlpTopic_Macro[j] = 0; 102 } 103 fclose( fSHG); 104 return nHotspots; 105} 106 107 108// Convert Windows .SHG file to HTML map file 109 110bool SHGToMap(wxChar *filename, wxChar *defaultFile) 111{ 112 // Test the SHG parser 113 HotSpot *hotspots = NULL; 114 int n = ParseSHG(filename, &hotspots); 115 if (n == 0) 116 return false; 117 118 wxChar buf[100]; 119 wxSnprintf(buf, sizeof(buf), _T("Converting .SHG file to HTML map file: there are %d hotspots in %s."), n, filename); 120 OnInform(buf); 121 122 wxChar outBuf[256]; 123 wxStrcpy(outBuf, filename); 124 StripExtension(outBuf); 125 wxStrcat(outBuf, _T(".map")); 126 127 FILE *fd = wxFopen(outBuf, _T("w")); 128 if (!fd) 129 { 130 OnError(_T("Could not open .map file for writing.")); 131 delete[] hotspots; 132 return false; 133 } 134 135 wxFprintf(fd, _T("default %s\n"), defaultFile); 136 for (int i = 0; i < n; i++) 137 { 138 wxChar *refFilename = _T("??"); 139 140 TexRef *texRef = FindReference(hotspots[i].szHlpTopic_Macro); 141 if (texRef) 142 refFilename = texRef->refFile; 143 else 144 { 145 wxChar buf[300]; 146 wxSnprintf(buf, sizeof(buf), _T("Warning: could not find hotspot reference %s"), hotspots[i].szHlpTopic_Macro); 147 OnInform(buf); 148 } 149 wxFprintf(fd, _T("rect %s %d %d %d %d\n"), refFilename, (int)hotspots[i].left, (int)hotspots[i].top, 150 (int)hotspots[i].right, (int)hotspots[i].bottom); 151 } 152 wxFprintf(fd, _T("\n")); 153 154 fclose(fd); 155 156 delete[] hotspots; 157 return true; 158} 159 160