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