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.

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