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 
ParseSHG(const wxChar * fileName,HotSpot ** hotspots)38 int   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 
SHGToMap(wxChar * filename,wxChar * defaultFile)110 bool 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