Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

533 lines
11 KiB

  1. #include "crane.h"
  2. #include <ASSERT.h>
  3. #define READ_BUF_SIZE 1024
  4. #define MAX_LINE 2048
  5. static wchar_t abuff[MAX_LINE];
  6. extern FEATURE_KIND gakind[];
  7. extern size_t gasize[];
  8. wchar_t *LastLineSample()
  9. {
  10. return abuff;
  11. }
  12. BOOL AllocFeature(SAMPLE *, int);
  13. void PutElement(FILE *fpo, void *pv, int type, wchar_t chSep)
  14. {
  15. int status;
  16. switch (type)
  17. {
  18. case typeBOOL:
  19. status = fwprintf(fpo, L"%c%c", chSep, *((BYTE *) pv) ? L'T' : L'F');
  20. ASSERT(status == 2);
  21. break;
  22. case typeBYTE:
  23. status = fwprintf(fpo, L"%c%02X", chSep, *((BYTE *) pv));
  24. ASSERT(status == 3);
  25. break;
  26. case type8DOT8:
  27. status = fwprintf(fpo, L"%c%04X", chSep, *((WORD *) pv));
  28. ASSERT(status == 5);
  29. break;
  30. case typeSHORT:
  31. status = fwprintf(fpo, L"%c%d", chSep, *((SHORT *) pv));
  32. ASSERT(status >= 2 && status <= 7);
  33. break;
  34. case typeUSHORT:
  35. status = fwprintf(fpo, L"%c%d", chSep, *((USHORT *) pv));
  36. ASSERT(status >= 2 && status <= 6);
  37. break;
  38. case typePOINTS:
  39. status = fwprintf(fpo, L"%c%d,%d", chSep, ((END_POINTS *) pv)->start, ((END_POINTS *) pv)->end);
  40. ASSERT(status >= 4 && status <= 14);
  41. break;
  42. case typeDRECTS:
  43. status = fwprintf(fpo, L"%c%d,%d,%d,%d", chSep, ((DRECTS *) pv)->x, ((DRECTS *) pv)->y, ((DRECTS *) pv)->w, ((DRECTS *) pv)->h);
  44. ASSERT(status >= 8 && status <= 28);
  45. break;
  46. case typeRECTS:
  47. status = fwprintf(fpo, L"%c%d,%d,%d,%d", chSep, ((RECTS *) pv)->x1, ((RECTS *) pv)->y1, ((RECTS *) pv)->x2, ((RECTS *) pv)->y2);
  48. ASSERT(status >= 8 && status <= 28);
  49. break;
  50. default:
  51. break;
  52. }
  53. }
  54. // Write out one featurized ink sample
  55. BOOL WriteSample(SAMPLE *_this, FILE *fpo)
  56. {
  57. int ifeat;
  58. int ielem;
  59. int cstrk;
  60. int size;
  61. int type;
  62. BYTE *base;
  63. // Get the stroke count
  64. cstrk = _this->cstrk;
  65. if ( fwprintf(fpo, L"%02d %04X <%s %d %d>", cstrk, _this->wchLabel, _this->aSampleFile, _this->ipanel, _this->ichar) < 15 ||
  66. fwprintf(fpo, L" %d %d,%d,%d,%d", _this->fDakuten, _this->drcs.x, _this->drcs.y, _this->drcs.w, _this->drcs.h) < 10 )
  67. {
  68. return FALSE;
  69. }
  70. for (ielem = 0; ielem < MAX_RECOG_ALTS; ielem++)
  71. {
  72. if ( fwprintf(fpo, L"%c%04X", ielem ? L',' : L' ', _this->awchAlts[ielem]) < 5 )
  73. {
  74. return FALSE;
  75. }
  76. }
  77. for (ifeat = 0; ifeat < FEATURE_COUNT; ifeat++)
  78. {
  79. // Get the number of elements in this feature
  80. switch (gakind[ifeat].freq)
  81. {
  82. case freqSTROKE:
  83. base = (BYTE *) (_this->apfeat[ifeat]->data);
  84. type = gakind[ifeat].type;
  85. size = gasize[type];
  86. for (ielem = 0; ielem < cstrk; ielem++)
  87. PutElement(fpo, (void *) (base + ielem * size), type, (wchar_t) (ielem ? L':' : L' '));
  88. break;
  89. case freqFEATURE:
  90. case freqSTEP:
  91. case freqPOINT:
  92. break;
  93. }
  94. // Print the element list
  95. }
  96. if ( fwprintf(fpo, L"\n") != 1 )
  97. {
  98. return FALSE;
  99. }
  100. return TRUE;
  101. }
  102. // Read a hexadecimal number
  103. wchar_t *GetHEXADEC(wchar_t *pbuff, long *pval)
  104. {
  105. wchar_t *pRef = pbuff;
  106. *pval = 0;
  107. while (iswxdigit(*pbuff))
  108. {
  109. *pval <<= 4;
  110. *pval += (BYTE)(*pbuff < L'A' ? *pbuff - L'0' : *pbuff - L'A' + 10);
  111. ++pbuff;
  112. }
  113. ASSERT(pRef + 1 <= pbuff);
  114. ASSERT(pRef + 8 >= pbuff);
  115. return pbuff;
  116. }
  117. // Read in a signed integer
  118. wchar_t *GetInteger(wchar_t *pbuff, long *pval)
  119. {
  120. wchar_t *pRef = pbuff;
  121. BOOL bNeg = FALSE;
  122. if (*pbuff == L'-')
  123. {
  124. pbuff++;
  125. bNeg = TRUE;
  126. }
  127. *pval = 0;
  128. while (iswdigit(*pbuff))
  129. {
  130. *pval *= 10;
  131. *pval += (BYTE)(*pbuff - L'0');
  132. ++pbuff;
  133. }
  134. if (bNeg)
  135. *pval = -(*pval);
  136. ASSERT(pRef + 1 + bNeg <= pbuff);
  137. ASSERT(pRef + 11 >= pbuff);
  138. return pbuff;
  139. }
  140. wchar_t *GetPOINT(wchar_t *pbuff, POINT *ppt)
  141. {
  142. if (((pbuff = GetInteger(pbuff, &ppt->x)) == (wchar_t *) NULL) || (*pbuff++ != L',')) {
  143. ASSERT(FALSE);
  144. return (wchar_t *) NULL;
  145. }
  146. return GetInteger(pbuff, &ppt->y);
  147. }
  148. wchar_t *GetRECT(wchar_t *pbuff, RECT *prc)
  149. {
  150. if (((pbuff = GetInteger(pbuff, &prc->left)) == (wchar_t *) NULL) || (*pbuff++ != L',')) {
  151. ASSERT(FALSE);
  152. return (wchar_t *) NULL;
  153. }
  154. if (((pbuff = GetInteger(pbuff, &prc->top)) == (wchar_t *) NULL) || (*pbuff++ != L',')) {
  155. ASSERT(FALSE);
  156. return (wchar_t *) NULL;
  157. }
  158. if (((pbuff = GetInteger(pbuff, &prc->right)) == (wchar_t *) NULL) || (*pbuff++ != L',')) {
  159. ASSERT(FALSE);
  160. return (wchar_t *) NULL;
  161. }
  162. return GetInteger(pbuff, &prc->bottom);
  163. }
  164. wchar_t *GetElement(wchar_t *pbuff, void *pv, int type)
  165. {
  166. long val;
  167. POINT pt;
  168. RECT rc;
  169. switch (type)
  170. {
  171. case typeBOOL:
  172. if (*pbuff == L'T')
  173. *((BYTE *) pv) = TRUE, pbuff++;
  174. else if (*pbuff == L'F')
  175. *((BYTE *) pv) = FALSE, pbuff++;
  176. else {
  177. ASSERT(FALSE);
  178. pbuff = (wchar_t *) NULL;
  179. }
  180. break;
  181. case typeBYTE:
  182. pbuff = GetHEXADEC(pbuff, &val);
  183. ASSERT(pbuff);
  184. *((BYTE *) pv) = (BYTE) val;
  185. break;
  186. case type8DOT8:
  187. pbuff = GetHEXADEC(pbuff, &val);
  188. ASSERT(pbuff);
  189. *((WORD *) pv) = (WORD) val;
  190. break;
  191. case typeSHORT:
  192. pbuff = GetInteger(pbuff, &val);
  193. ASSERT(pbuff);
  194. *((short *) pv) = (short) val;
  195. break;
  196. case typeUSHORT:
  197. pbuff = GetInteger(pbuff, &val);
  198. ASSERT(pbuff);
  199. *((USHORT *) pv) = (USHORT) val;
  200. break;
  201. case typePOINTS:
  202. pbuff = GetPOINT(pbuff, &pt);
  203. ASSERT(pbuff);
  204. ((END_POINTS *) pv)->start = (short) pt.x;
  205. ((END_POINTS *) pv)->end = (short) pt.y;
  206. break;
  207. case typeDRECTS:
  208. pbuff = GetRECT(pbuff, &rc);
  209. ASSERT(pbuff);
  210. ((DRECTS *) pv)->x = (short) rc.left;
  211. ((DRECTS *) pv)->y = (short) rc.top;
  212. ((DRECTS *) pv)->w = (short) rc.right;
  213. ((DRECTS *) pv)->h = (short) rc.bottom;
  214. break;
  215. case typeRECTS:
  216. pbuff = GetRECT(pbuff, &rc);
  217. ASSERT(pbuff);
  218. ((RECTS *) pv)->x1 = (short) rc.left;
  219. ((RECTS *) pv)->y1 = (short) rc.top;
  220. ((RECTS *) pv)->x2 = (short) rc.right;
  221. ((RECTS *) pv)->y2 = (short) rc.bottom;
  222. break;
  223. default:
  224. pbuff = (wchar_t *) NULL;
  225. ASSERT(pbuff);
  226. break;
  227. }
  228. return pbuff;
  229. }
  230. // Read in a feature list. This will allocate the sample if needed as well as all the space
  231. // needed to store the feature lists.
  232. SAMPLE *DoReadSample(SAMPLE *_this)
  233. {
  234. BOOL bAlloc = FALSE;
  235. BOOL bFailed = FALSE;
  236. int ifeat;
  237. int ielem;
  238. int type;
  239. int size;
  240. BYTE *base;
  241. wchar_t *pbuff;
  242. unsigned long uLong;
  243. int status;
  244. if (_this == (SAMPLE *) NULL)
  245. {
  246. if ((_this = (SAMPLE *) ExternAlloc(sizeof(SAMPLE))) == (SAMPLE *) NULL) {
  247. ASSERT(FALSE);
  248. return (SAMPLE *) NULL;
  249. }
  250. bAlloc = TRUE;
  251. }
  252. InitFeatures(_this);
  253. // Get the first items: stroke count, codepoint, file name and file index
  254. status = swscanf(abuff, L"%2d %4X <%s %d %d>", &_this->cstrk, &_this->wchLabel, _this->aSampleFile, &_this->ipanel, &_this->ichar);
  255. if (status != 5) {
  256. return (SAMPLE *) NULL;
  257. }
  258. // Position the input cursor to the space just after the closing angle bracket of the file info
  259. pbuff = abuff;
  260. while (*pbuff && (*pbuff++ != L'>'))
  261. ;
  262. if (pbuff < abuff + 15) {
  263. return (SAMPLE *) NULL;
  264. }
  265. if (pbuff > abuff + 50) {
  266. return (SAMPLE *) NULL;
  267. }
  268. // The dakuten and guide features live directly in the sample, handle them
  269. pbuff = GetElement(++pbuff, (void *) &_this->fDakuten, typeSHORT);
  270. if (!pbuff) {
  271. return (SAMPLE *) NULL;
  272. }
  273. pbuff = GetElement(++pbuff, (void *) &_this->drcs, typeDRECTS);
  274. if (!pbuff) {
  275. return (SAMPLE *) NULL;
  276. }
  277. // The Zilla alternate list comes next
  278. ++pbuff; // Skip space
  279. pbuff = GetHEXADEC(pbuff, &uLong);
  280. if (!pbuff) {
  281. return (SAMPLE *) NULL;
  282. }
  283. _this->awchAlts[0] = (wchar_t)uLong;
  284. for (ielem = 1; ielem < MAX_RECOG_ALTS && pbuff && *pbuff++ == L','; ielem++)
  285. {
  286. pbuff = GetHEXADEC(pbuff, &uLong);
  287. if (!pbuff) {
  288. return (SAMPLE *) NULL;
  289. }
  290. _this->awchAlts[ielem] = (wchar_t)uLong;
  291. }
  292. // Allocate the remaining features and read them. If the cursor is ever pointing
  293. // at something we don't expect, panic.
  294. for (ifeat = 0; ifeat < FEATURE_COUNT; ifeat++)
  295. {
  296. if (bFailed || !AllocFeature(_this, ifeat) || *pbuff != L' ')
  297. {
  298. FreeFeatures(_this);
  299. if (bAlloc)
  300. ExternFree(_this);
  301. ASSERT(FALSE);
  302. return (SAMPLE *) NULL;
  303. }
  304. // OK, now we have space to store the results
  305. switch (gakind[ifeat].freq)
  306. {
  307. case freqSTROKE:
  308. base = (BYTE *) (_this->apfeat[ifeat]->data);
  309. type = gakind[ifeat].type;
  310. size = gasize[type];
  311. for (ielem = 0; ielem < _this->cstrk; ielem++)
  312. {
  313. // Each element should be preceded by a colon
  314. if (ielem && (*pbuff != L':'))
  315. bFailed = TRUE;
  316. pbuff = GetElement(++pbuff, (void *) (base + ielem * size), type);
  317. if (pbuff == (wchar_t *) NULL) {
  318. ASSERT(pbuff);
  319. bFailed = TRUE;
  320. break;
  321. }
  322. }
  323. break;
  324. case freqFEATURE:
  325. case freqSTEP:
  326. case freqPOINT:
  327. break;
  328. }
  329. }
  330. if (bFailed)
  331. {
  332. FreeFeatures(_this);
  333. if (bAlloc)
  334. ExternFree(_this);
  335. ASSERT(FALSE);
  336. return (SAMPLE *) NULL;
  337. }
  338. return _this;
  339. }
  340. // Read using stdio library.
  341. SAMPLE *ReadSample(SAMPLE *_this, FILE *fpi)
  342. {
  343. if (!fgetws(abuff, MAX_LINE, fpi)) {
  344. ASSERT(feof(fpi));
  345. return (SAMPLE *) NULL;
  346. }
  347. return DoReadSample(_this);
  348. }
  349. // EOF Flag for DoLineRead used by ReadSampleH
  350. static int g_fEOF = FALSE;
  351. // Reset EOF Flag for DoLineRead.
  352. void ResetReadSampleH()
  353. {
  354. g_fEOF = FALSE;
  355. }
  356. // Read one line of input.
  357. BOOL DoLineRead(HANDLE hFile, wchar_t *pBuf, int sizeBuf)
  358. {
  359. static int iReadBuf = 0;
  360. static int cReadBuf = 0;
  361. static BYTE aReadBuf[READ_BUF_SIZE];
  362. BOOL fHaveCR;
  363. int cBuf;
  364. // Check for end of file on last call.
  365. if (g_fEOF) {
  366. return FALSE;
  367. }
  368. // Make sure we keep room for null.
  369. --sizeBuf;
  370. // Loop until we have a full line.
  371. cBuf = 0;
  372. fHaveCR = FALSE;
  373. while (TRUE) {
  374. DWORD bytesRead;
  375. // Make sure we have something in the buffer.
  376. if (iReadBuf == cReadBuf) {
  377. if (!ReadFile(hFile, aReadBuf, READ_BUF_SIZE, &bytesRead, NULL)) {
  378. // Read error!
  379. ASSERT(0);
  380. return FALSE;
  381. }
  382. if (bytesRead == 0) {
  383. // EOF
  384. g_fEOF = TRUE;
  385. pBuf[cBuf] = L'\0';
  386. return cBuf != 0;
  387. }
  388. cReadBuf = bytesRead;
  389. iReadBuf = 0;
  390. }
  391. // If we had a CR last time we must have a LF this time.
  392. if (fHaveCR) {
  393. if (aReadBuf[iReadBuf] == '\n') {
  394. ++iReadBuf;
  395. } else {
  396. // Missing LF?!?!
  397. ASSERT(0);
  398. }
  399. break;
  400. }
  401. // Copy one character, checking for end of line.
  402. // We convert to Unicode, but since we just use
  403. // plain ASCII, so all we do is zero extend.
  404. if (aReadBuf[iReadBuf] == '\r') {
  405. ++iReadBuf;
  406. fHaveCR = TRUE;
  407. } else if (aReadBuf[iReadBuf] == '\n') {
  408. // Floating NL?!?!
  409. ++iReadBuf;
  410. break;
  411. } else {
  412. if (cBuf >= sizeBuf) {
  413. // Line too long!
  414. ASSERT(0);
  415. break;
  416. }
  417. pBuf[cBuf++] = (wchar_t)aReadBuf[iReadBuf++];
  418. }
  419. }
  420. // Terminate string and return.
  421. pBuf[cBuf] = L'\0';
  422. return TRUE;
  423. }
  424. // Read using Windows calls.
  425. SAMPLE *ReadSampleH(SAMPLE *_this, HANDLE hFile)
  426. {
  427. // Outer loop to deal with stuped COPY comand putting ^Z characters in the file.
  428. do {
  429. if (!DoLineRead(hFile, abuff, MAX_LINE)){
  430. return (SAMPLE *)-1;
  431. }
  432. } while (abuff[0] == L'\x1a' && abuff[1] == L'\0');
  433. return DoReadSample(_this);
  434. }