PageRenderTime 52ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/nookCrossWord/src/com/nookdevs/crossword/PuzzlePuz.java

http://nookdevs.googlecode.com/
Java | 259 lines | 222 code | 10 blank | 27 comment | 60 complexity | 57f7987851ce4cae1116b41942c324ff MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception
  1. /*
  2. * Copyright 2010 nookDevs
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. package com.nookdevs.crossword;
  16. import java.io.RandomAccessFile;
  17. import java.nio.ByteBuffer;
  18. import java.nio.ByteOrder;
  19. import java.util.ArrayList;
  20. //import java.util.StringTokenizer;
  21. //import android.content.Context;
  22. import android.util.Log;
  23. public class PuzzlePuz {
  24. private String mChecksum;
  25. private String mFileMagic;
  26. private String mCIBCS;
  27. private String mMaskLowCS;
  28. private String mMaskHighCS;
  29. private String mVersion;
  30. private String mBIC;
  31. private int mRow;
  32. private int mCol;
  33. private int mNumClues;
  34. private String mSolString;
  35. private String mGrid;
  36. private String mTitle;
  37. private String mAuthor;
  38. private String mCopyRight;
  39. private ArrayList<Clue> mClues;
  40. private String mNotes;
  41. private String mFile;
  42. private CrossWord mActivity;
  43. private ArrayList<int[]> mCircles;
  44. private ArrayList<int[]> mShades;
  45. private ArrayList<int[]> mRebusCells;
  46. private ArrayList<String> mRebusValues;
  47. private String mExtrasGrid;
  48. private boolean mFormatSupportsRebus;
  49. private static final String LOGTAG=".Puz Parser:";
  50. public static final int VERSION_INDEX=0x18;
  51. public static final int COL_INDEX=0x2C;
  52. public static final int TITLE_INDEX=0x32;
  53. // public static void main(String []s ) {
  54. // PuzzlePuz p = new PuzzlePuz(null);
  55. // p.loadPuzzle("f:\\test.puz");
  56. // }
  57. public PuzzlePuz(CrossWord activity) {
  58. mActivity = activity;
  59. }
  60. Puzzle loadPuzzle(String file) {
  61. Puzzle puzzle = null ;
  62. try {
  63. if ( !file.toLowerCase().endsWith(".puz")) {
  64. Log.e(this.toString(), "Not a valid puz file: " + file);
  65. return null;
  66. }
  67. RandomAccessFile fp = new RandomAccessFile(file, "r");
  68. fp.seek(VERSION_INDEX);
  69. byte[] buffer = new byte[3];
  70. fp.read(buffer, 0, 3);
  71. mVersion = new String(buffer, "Windows-1252");
  72. if ( mVersion.equals("1.2") || mVersion.equals("1.1") || mVersion.equals("1.0") || mVersion.startsWith("0.") ) {
  73. mFormatSupportsRebus = false ;
  74. } else {
  75. mFormatSupportsRebus = true ;
  76. }
  77. fp.seek(COL_INDEX);
  78. mCol = fp.readByte();
  79. //System.out.println("Cols =" + mCol);
  80. mRow = fp.readByte();
  81. //System.out.println("Rows =" + mRow);
  82. mNumClues = Short.reverseBytes(fp.readShort());
  83. //System.out.println("NumClues =" + mNumClues);
  84. fp.skipBytes(2);
  85. int scrambled = fp.readShort();
  86. if( scrambled != 0) {
  87. Log.e(this.toString(), "File appears to be scrambled...");
  88. }
  89. buffer = new byte[mRow * mCol];
  90. fp.read(buffer, 0,mRow*mCol);
  91. mSolString = new String(buffer, "Windows-1252");
  92. fp.read(buffer, 0, mRow*mCol);
  93. mGrid = new String(buffer,"Windows-1252");
  94. int size =(int)(fp.length() - fp.getFilePointer());
  95. buffer = new byte[size];
  96. fp.read(buffer, 0, size);
  97. String tmp = new String(buffer,"Windows-1252");
  98. String[] data= tmp.split("\0");
  99. if( data == null || data.length < 3+mNumClues) {
  100. Log.e(this.toString(), "File appears to be corrupted...");
  101. return null;
  102. }
  103. mTitle = data[0];
  104. mAuthor = data[1];
  105. mCopyRight = data[2];
  106. mClues = new ArrayList<Clue>(mNumClues);
  107. int i=3;
  108. int x=0;
  109. int y=0;
  110. int num=1;
  111. boolean accepted=false;
  112. while( true) {
  113. if( mGrid.charAt(x + mCol*y) == '.') {
  114. // ignore
  115. } else {
  116. if ( x ==0 || mGrid.charAt(x -1 + mCol*y) == '.') {
  117. if( x < mCol-1 && mGrid.charAt(x+1 +mCol*y) !='.') {
  118. Clue clue = new Clue(data[i++], CrossWord.ACROSS, num, y, x);
  119. mClues.add(clue);
  120. accepted=true;
  121. }
  122. }
  123. if( y ==0 || mGrid.charAt( x + mCol*(y-1)) =='.') {
  124. if( y < mRow-1 && mGrid.charAt(x +mCol*(y+1)) !='.') {
  125. Clue clue = new Clue(data[i++], CrossWord.DOWN, num, y, x);
  126. mClues.add(clue);
  127. accepted=true;
  128. }
  129. }
  130. if( accepted) {
  131. num++;
  132. accepted=false;
  133. }
  134. }
  135. x++;
  136. if ( x == mCol) {
  137. x=0;
  138. y++;
  139. }
  140. if( y == mRow) {
  141. break;
  142. }
  143. }
  144. if( i < data.length) {
  145. mNotes = data[i++];
  146. } else
  147. mNotes=null;
  148. int c=0;
  149. for(int k=0; k< i; k++) {
  150. c += data[k] != null?data[k].length()+1:1;
  151. }
  152. if( i < data.length){
  153. fp.close();
  154. loadExtraFields(buffer, c);
  155. } else {
  156. fp.close();
  157. }
  158. puzzle = new Puzzle(mActivity, file, mRow, mCol, mSolString, mCircles, mShades,
  159. mFormatSupportsRebus, mRebusCells, mRebusValues, mClues, mTitle, mAuthor, mCopyRight,null,null,null, mNotes) ;
  160. } catch(Exception ex) {
  161. Log.e(this.toString(), "Error parsing file " + file + " " + ex.getMessage(), ex);
  162. return null;
  163. }
  164. return puzzle;
  165. }
  166. private void loadExtraFields(byte[] buffer, int c) {
  167. int[][] mGridRebusLocations = null ;
  168. String mRebusTableString = null ;
  169. try {
  170. int i = c;
  171. while( i < buffer.length) {
  172. String keyword = ""+ (char)buffer[i++] + (char)buffer[i++] + (char)buffer[i++] + (char)buffer[i++];
  173. ByteBuffer bb = ByteBuffer.allocate(2);
  174. bb.order(ByteOrder.LITTLE_ENDIAN);
  175. bb.put(buffer[i++]);
  176. bb.put(buffer[i++]);
  177. int size = bb.getShort(0);
  178. i+=2; // skip checksum
  179. if( keyword != null && keyword.equals("GRBS") && (size == mRow*mCol) ) {
  180. //load rebus table
  181. mGridRebusLocations = new int [mCol][mRow];
  182. ByteBuffer b = ByteBuffer.allocate(1);
  183. b.order(ByteOrder.LITTLE_ENDIAN);
  184. for(int x = 0; x < mCol ; x++) {
  185. for(int y = 0 ; y < mRow; y++) {
  186. b.clear();
  187. b.put( buffer[ i + (x + mCol*y) ] );
  188. mGridRebusLocations[x][y] = (int)b.get(0) ;
  189. }
  190. }
  191. i+=size;
  192. i+=1; //Null
  193. } else if(keyword.equals("RTBL")) {
  194. mRebusTableString = new String( buffer, i, size, "Windows-1252");
  195. i+=size;
  196. i+=1; //Null
  197. } else if(keyword.equals("GEXT")) {
  198. mExtrasGrid = new String( buffer,i, size,"Windows-1252");
  199. mCircles = new ArrayList<int[]>();
  200. for(int k=0; k< size; k++) {
  201. int c1 = buffer[k+i];
  202. if( (c1 & 0x80) !=0) {
  203. int [] pos = new int[2];
  204. pos[0] = (k)/mRow;
  205. pos[1] = (k) - pos[0]*mRow;
  206. mCircles.add(pos);
  207. }
  208. }
  209. i+=size;
  210. i++; //Null
  211. } else if(keyword.equals("RUSR")) {
  212. i+=size;
  213. i+=1; //Null
  214. } else if( keyword.equals("LTIM")) {
  215. i+= size;
  216. i+=1; //Null
  217. }
  218. else {
  219. Log.e(LOGTAG, "Unknown section in file. Ignoring... " + keyword);
  220. //assuming same structure as others.
  221. i+=size;
  222. i+=1;
  223. }
  224. }
  225. // If there were any rebus entries, interpret them:
  226. if ( mRebusTableString != null && mGridRebusLocations != null ) {
  227. mRebusCells = new ArrayList<int[]>() ;
  228. mRebusValues = new ArrayList<String>() ;
  229. String[] tokens = mRebusTableString.split(";");
  230. for( String token : tokens ) {
  231. String numString = token.substring(0,2).trim();
  232. int rebusKeyNum = Integer.parseInt(numString) + 1 ;
  233. String rebusString = token.substring(3);
  234. for(int x = 0; x < mCol ; x++) {
  235. for(int y = 0 ; y < mRow; y++) {
  236. if ( mGridRebusLocations[x][y] == rebusKeyNum ) {
  237. int loc[] = { y, x } ; // row,col
  238. mRebusCells.add(loc);
  239. mRebusValues.add(rebusString);
  240. }
  241. }
  242. }
  243. }
  244. }
  245. } catch(Exception ex) {
  246. Log.e(LOGTAG, "Exception while reading extra data:"+ex.getMessage(), ex);
  247. }
  248. }
  249. }