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