Leaked source code of windows server 2003
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.

313 lines
8.0 KiB

  1. /****************************Module*Header***********************************\
  2. * Module Name: INPUT.C
  3. *
  4. * Module Descripton: Decimal floating point input
  5. *
  6. * Warnings:
  7. *
  8. * Created:
  9. *
  10. * Author:
  11. \****************************************************************************/
  12. #include "scicalc.h"
  13. #include "unifunc.h"
  14. #include "input.h"
  15. #include "strsafe.h"
  16. extern BOOL gbRecord;
  17. extern TCHAR szDec[5]; // The decimal point we use
  18. extern INT gcIntDigits;
  19. TCHAR const szZeroInit[] = TEXT("0");
  20. #define CH_BASE_10_EXP TEXT('e')
  21. #define CH_BASE_X_EXP TEXT('^')
  22. /****************************************************************************/
  23. void CIO_vClearNSec( PCALCNUMSEC pcns ) {
  24. pcns->fEmpty = TRUE;
  25. pcns->fNeg = FALSE;
  26. // Reference input.h for string length for pcns->szVal
  27. StringCchCopy(pcns->szVal, MAX_STRLEN+1, szZeroInit);
  28. pcns->cchVal = lstrlen(pcns->szVal);
  29. }
  30. void CIO_vClear(PCALCINPUTOBJ pcio)
  31. {
  32. CIO_vClearNSec( &(pcio->cnsNum) );
  33. CIO_vClearNSec( &(pcio->cnsExp) );
  34. pcio->fExp = FALSE;
  35. pcio->iDecPt = -1;
  36. }
  37. /****************************************************************************/
  38. void CIO_vConvertToNumObj(PHNUMOBJ phnoNum, PCALCINPUTOBJ pcio)
  39. {
  40. HNUMOBJ hnoValue;
  41. LPTSTR pszExp = NULL;
  42. // ZTerm the strings
  43. pcio->cnsNum.szVal[pcio->cnsNum.cchVal] = TEXT('\0');
  44. if (pcio->fExp ) {
  45. pszExp = pcio->cnsExp.szVal;
  46. pszExp[pcio->cnsExp.cchVal] = TEXT('\0');
  47. }
  48. hnoValue = NumObjMakeNumber( pcio->cnsNum.fNeg, pcio->cnsNum.szVal, pcio->cnsExp.fNeg, pszExp );
  49. NumObjAssign( phnoNum, hnoValue );
  50. return;
  51. }
  52. /****************************************************************************/
  53. void CIO_vConvertToString(LPTSTR *ppszOut, int* pcchszOut, PCALCINPUTOBJ pcio, int nRadix)
  54. {
  55. //In theory both the base and exponent could be C_NUM_MAX_DIGITS long.
  56. #define CCHMAXTEMP C_NUM_MAX_DIGITS*2+4
  57. TCHAR szTemp[CCHMAXTEMP];
  58. LPTSTR psz;
  59. int i;
  60. // ZTerm the strings
  61. pcio->cnsNum.szVal[pcio->cnsNum.cchVal] = TEXT('\0');
  62. if ( pcio->fExp )
  63. pcio->cnsExp.szVal[pcio->cnsExp.cchVal] = TEXT('\0');
  64. i = 0;
  65. if (pcio->cnsNum.fNeg)
  66. szTemp[i++] = TEXT('-');
  67. StringCchCopy(&szTemp[i], CCHMAXTEMP - i, pcio->cnsNum.szVal);
  68. i += pcio->cnsNum.cchVal;
  69. // Add a '.' if it is not already there
  70. if (pcio->iDecPt == -1 )
  71. szTemp[i++] = szDec[0];
  72. if (pcio->fExp) {
  73. szTemp[i++] = nRadix == 10 ? CH_BASE_10_EXP : CH_BASE_X_EXP;
  74. if (pcio->cnsExp.fNeg)
  75. szTemp[i++] = TEXT('-');
  76. else
  77. szTemp[i++] = TEXT('+');
  78. StringCchCopy(&szTemp[i], CCHMAXTEMP - i, pcio->cnsExp.szVal);
  79. i += pcio->cnsExp.cchVal;
  80. }
  81. int cchszOut = lstrlen( szTemp ) + 1;
  82. psz = (LPTSTR)NumObjAllocMem( cchszOut * sizeof(TCHAR) );
  83. if (psz) {
  84. if (*ppszOut != NULL) {
  85. NumObjFreeMem( *ppszOut );
  86. }
  87. *ppszOut = psz;
  88. *pcchszOut = cchszOut;
  89. }
  90. // Don't show '.' if in int math
  91. if (F_INTMATH() && szTemp[i-1] == szDec[0])
  92. i--;
  93. szTemp[i] = TEXT('\0');
  94. StringCchCopy(*ppszOut, *pcchszOut, szTemp);
  95. return;
  96. }
  97. /****************************************************************************/
  98. BOOL CIO_bAddDigit(PCALCINPUTOBJ pcio, int iValue)
  99. {
  100. PCALCNUMSEC pcns;
  101. TCHAR chDigit;
  102. int cchMaxDigits;
  103. // convert from an integer into a character
  104. chDigit = (iValue < 10)?(TEXT('0')+iValue):(TEXT('A')+iValue-10);
  105. if (pcio->fExp)
  106. {
  107. pcns = &(pcio->cnsExp);
  108. cchMaxDigits = C_EXP_MAX_DIGITS;
  109. }
  110. else
  111. {
  112. pcns = &(pcio->cnsNum);
  113. ASSERT( gcIntDigits <= C_NUM_MAX_DIGITS );
  114. cchMaxDigits = gcIntDigits;
  115. }
  116. // Ignore leading zeros
  117. if ( pcns->fEmpty && (iValue == 0) )
  118. {
  119. return TRUE;
  120. }
  121. if ( pcns->cchVal < cchMaxDigits )
  122. {
  123. if (pcns->fEmpty)
  124. {
  125. pcns->cchVal = 0; // Clobber the default zero
  126. pcns->fEmpty = FALSE;
  127. }
  128. pcns->szVal[pcns->cchVal++] = chDigit;
  129. return TRUE;
  130. }
  131. // if we are in base 8 entering a mantica and we're on the last digit then
  132. // there are special cases where we can actually add one more digit.
  133. if ( nRadix == 8 && pcns->cchVal == cchMaxDigits && !pcio->fExp )
  134. {
  135. BOOL bAllowExtraDigit = FALSE;
  136. switch ( dwWordBitWidth % 3 )
  137. {
  138. case 1:
  139. // in 16bit word size, if the first digit is a 1 we can enter 6 digits
  140. if ( pcns->szVal[0] == TEXT('1') )
  141. bAllowExtraDigit = TRUE;
  142. break;
  143. case 2:
  144. // in 8 or 32bit word size we get an extra digit if the first digit is 3 or less
  145. if ( pcns->szVal[0] <= TEXT('3') )
  146. bAllowExtraDigit = TRUE;
  147. break;
  148. }
  149. if ( bAllowExtraDigit )
  150. {
  151. pcns->szVal[pcns->cchVal++] = chDigit;
  152. return TRUE;
  153. }
  154. }
  155. return FALSE;
  156. }
  157. /****************************************************************************/
  158. void CIO_vToggleSign(PCALCINPUTOBJ pcio)
  159. {
  160. // Zero is always positive
  161. if (pcio->cnsNum.fEmpty)
  162. {
  163. pcio->cnsNum.fNeg = FALSE;
  164. pcio->cnsExp.fNeg = FALSE;
  165. }
  166. else if (pcio->fExp)
  167. {
  168. pcio->cnsExp.fNeg = !pcio->cnsExp.fNeg;
  169. }
  170. else
  171. {
  172. pcio->cnsNum.fNeg = !pcio->cnsNum.fNeg;
  173. }
  174. }
  175. /****************************************************************************/
  176. BOOL CIO_bAddDecimalPt(PCALCINPUTOBJ pcio)
  177. {
  178. ASSERT(gbRecord == TRUE);
  179. if (pcio->iDecPt != -1) // Already have a decimal pt
  180. return FALSE;
  181. if (pcio->fExp) // Entering exponent
  182. return FALSE;
  183. pcio->cnsNum.fEmpty = FALSE; // Zeros become significant
  184. pcio->iDecPt = pcio->cnsNum.cchVal++;
  185. pcio->cnsNum.szVal[pcio->iDecPt] = szDec[0];
  186. return TRUE;
  187. }
  188. /****************************************************************************/
  189. BOOL CIO_bExponent(PCALCINPUTOBJ pcio)
  190. {
  191. ASSERT(gbRecord == TRUE);
  192. // For compatability, add a trailing dec pnt to base num if it doesn't have one
  193. CIO_bAddDecimalPt( pcio );
  194. if (pcio->fExp) // Already entering exponent
  195. return FALSE;
  196. pcio->fExp = TRUE; // Entering exponent
  197. return TRUE;
  198. }
  199. /****************************************************************************/
  200. BOOL CIO_bBackspace(PCALCINPUTOBJ pcio)
  201. {
  202. ASSERT(gbRecord == TRUE);
  203. if (pcio->fExp)
  204. {
  205. if ( !(pcio->cnsExp.fEmpty) )
  206. {
  207. pcio->cnsExp.cchVal--;
  208. if (pcio->cnsExp.cchVal == 0)
  209. {
  210. CIO_vClearNSec( &(pcio->cnsExp) );
  211. }
  212. }
  213. else
  214. {
  215. pcio->fExp = FALSE;
  216. }
  217. }
  218. else
  219. {
  220. if ( !(pcio->cnsNum.fEmpty) )
  221. {
  222. pcio->cnsNum.cchVal--;
  223. }
  224. if ( pcio->cnsNum.cchVal <= pcio->iDecPt )
  225. //Backed up over decimal point
  226. pcio->iDecPt = -1;
  227. if ((pcio->cnsNum.cchVal == 0) || ((pcio->cnsNum.cchVal == 1) && (pcio->cnsNum.szVal[0] == TEXT('0'))))
  228. CIO_vClearNSec( &(pcio->cnsNum) );
  229. }
  230. return TRUE;
  231. }
  232. /****************************************************************************/
  233. void CIO_vUpdateDecimalSymbol(PCALCINPUTOBJ pcio, TCHAR chLastDP)
  234. {
  235. int iDP;
  236. ASSERT(pcio);
  237. iDP = pcio->iDecPt; // Find the DP index
  238. if (iDP == -1)
  239. return;
  240. ASSERT(pcio->cnsNum.szVal[iDP] == chLastDP);
  241. pcio->cnsNum.szVal[iDP] = szDec[0]; // Change to new decimal pt
  242. }
  243. /****************************************************************************/