📄 floatfld.c
字号:
/********************************************************************* FILE: FloatFld.c** DESCRIPTION: Floating Point fields project.** VERSION: 1.0**********************************************************************/#include <PalmOS.h>#include <PalmCompatibility.h>#include "FloatFld.h"#include "FloatFldRsc.h"#include "Utils.h"#include "UtilsRsc.h"/************************************ * FUNCTION: SetPopup * * DESCRIPTION: Set a popup list's value. * * RETURNED: Nothing ************************************/ static void SetPopup( UInt16 popID, // ( in ) the popup trigger ID UInt16 listID, // ( in ) the popup list ID Int16 val // ( in ) the value to set the list too){ ControlPtr triggerP; ListPtr listP; Char * labelP; FormPtr frmP = FrmGetActiveForm (); if ( frmP ) { // Get the trigger and list pointers triggerP = GetObjectPtr ( popID ); listP = GetObjectPtr ( listID ); if ( triggerP && listP ) { // Get the current list text and set the trigger label LstSetSelection ( listP, val ); labelP = LstGetSelectionText ( listP, val ); CtlSetLabel ( triggerP, labelP ); } }}/************************************ * FUNCTION: HandlePopup * * DESCRIPTION: Handle a popup list control select event * by getting the user's new selection and * setting the list to it. This routine requires that * the popup List ID value is one greater than * the popup trigger ID. * * RETURNED: nothing ************************************/static void HandlePopup( UInt16 popID // ( in ) the popup trigger ID){ Int16 oldval; Int16 newval; ListPtr lstP = GetObjectPtr ( popID + 1 ); if ( lstP != NULL ) { oldval = LstGetSelection ( lstP ); newval = LstPopupList ( lstP ); if ( newval != noListSelection && oldval != newval ) { SetPopup ( popID, popID + 1, newval ); } }}/************************************ * FUNCTION: MoveToNextField * * DESCRIPTION: Change the focus to the next or previous field. * * RETURNED: nothing ************************************/static void MoveToNextField( FormPtr frmP, // ( in ) active form pointer UInt8 key // ( in) next/prev field character){ FieldPtr fldP; FieldAttrType attr; Int8 direction = key == nextFieldChr? ( Int8 ) 1: ( Int8 ) -1;// Get the current focus UInt16 focusIdx = FrmGetFocus ( frmP ); Int16 newFocusIdx = ( Int16 ) focusIdx; // If there is a focus, loop thru the form objects for another editable field if ( focusIdx != noFocus ) { Int16 numObjs = ( Int16 ) FrmGetNumberOfObjects ( frmP ); UInt8 i; for ( i = 0; i < numObjs; i ++ ) { // Point to the next/prev field newFocusIdx = newFocusIdx + direction; if ( newFocusIdx < 0 ) newFocusIdx = numObjs - 1; if ( newFocusIdx >= numObjs ) newFocusIdx = 0; // Check the current field to see if it's editable and visible fldP = FrmGetObjectPtr ( frmP, ( UInt16 ) newFocusIdx ); FldGetAttributes ( fldP, &attr ); if ( attr.editable && attr.visible ) {// Yes it is, set the focus FrmSetFocus ( frmP, ( UInt16 ) newFocusIdx ); break; } } }}#pragma mark ----------------/************************************ * FUNCTION: StringToDouble * * DESCRIPTION: Extract a double-size floating point number from a string. * The string may have a leading negative sign and a * decimal point. Non-numeric characters are ignored. * * RETURNED: The converted result ************************************/static double StringToDouble // ( out ) the converted result( Char * strP // ( in ) the string to convert){ double result; double divisor = 1.0; UInt8 srcP = 0; // Strip off and convert everything to the left of the decimal point while ( strP [ srcP ] != '\0' && strP [ srcP ] != gDSep ) { if ( TxtCharIsDigit ( strP [ srcP ] )) { result = result * 10.0 + ( strP [ srcP ] - '0' ); } srcP++; }// Strip off and convert everything to the right of the decimal while ( strP [ srcP ] != '\0' ) { if ( TxtCharIsDigit ( strP [ srcP ] )) { divisor = divisor / 10.0; result = result + (( strP [ srcP ] - '0' ) * divisor ); } srcP++; }// Adjust for negative result if necessary if ( strP [ 0 ] == '-' ) { result = - result; } return result;}/************************************ * FUNCTION: DoubleToString * * DESCRIPTION: Convert a double floating point # to a localized string. * The string may have a leading negative sign * and one decimal point. The result is undefined if * either the lefthand or righthand side of the incoming * value has more than MAX_LHS_DIGITS digits or * MAX_RHS_DIGITS. If the resulting string is greater * than maxLen, it's filled wih an overflow character (">") * and truncated to maxLen. The right-hand side is * zero filled up to precision digits. The caller is responsible for * making sure the destination char array is large enough. * Maxiumum useful precision is about 16 digits. * * RETURNED: Result put in parameter dstP. **************************************************/static void DoubleToString( double val, // ( in ) double to convert Char * dstP, // ( out ) place to put the result Boolean localize, // ( in ) localize with decimal separator? UInt8 precision, // ( in ) max # of digits on RHS UInt8 maxLen // ( in ) max # chars that can appear in result){ Char str [ MAX_LHS_DIGITS + 7 ]; // for LHS + punctuation UInt8 strIdx = sizeof ( str ) - 1; // index into str UInt8 digitCnt = 0; // digit counter UInt8 len; // string/substring length double LHSd; // the left-hand side value double RHSd; // the right-hand side value double digitd; // the current digit ( double ) long long digitll; // the current digit ( long long ) Char digit; // the current digit ( char ) Char * altDstP = dstP; // Negative. Mark final as negative & switch to absolute value// to make computations easier. if ( val < 0.0 ) { *dstP++ = '-'; // start final string with "-" val = - val; // work with abs value } // Split out the left and right-hand sides of the number LHSd = ( double ) ( long long ) val; RHSd = val - LHSd; str [ strIdx-- ] = '\0';// Strip off everything to the left of the decimal first,// inserting decimal separator characters as needed.// Store from the rightmost char to the leftmost in temp char array.// The result of grabbing digitll using a (long long ) conversion// is less than 100% accurate if digitCnt > 15. while ( LHSd >= 1.0 && digitCnt < MAX_LHS_DIGITS ) { // Insert a decimal separator if appropriate if ( localize && digitCnt % 3 == 0 && digitCnt > 0 ) str [ strIdx-- ] = gKSep; // Get the next digit digitll = ( long long ) ( LHSd / 10.0 ); digitd = (( double ) digitll ) * 10.0; digit = ( Char ) ( '0' + ( Char ) ( LHSd - digitd )); // Stuff it in a temporary char array digitCnt++, str [ strIdx-- ] = digit; LHSd = ( double ) digitll; } // Finished left-hand side, store the result in the destination array StrCopy ( dstP, &str [ strIdx + 1 ] ); // adds terminating NULL // get the fractional part if required, adding trailing zeroes if space.// Store the picked off digits right in the destination array. if ( precision > 0 ) { // Prep destination pointer and termination check values dstP = dstP + StrLen ( dstP ); len = ( UInt8 ) StrLen ( altDstP ); digitCnt = 0; // Add a decimal point to the destionation buffer len++, *dstP++ = gDSep; // Pick off digits until the remainder is very small. Zero fill to// precision. Stop zero filling if maxLen is reached to avoid// triggering overflow indication merely by zero filling. while ( digitCnt < precision ) { digitCnt++; // Get the next digit if there's still a significant portion of the// number available. The (long long) conversion makes digits past// VERY_SMALL_NUM most likely inaccurate, so why bother? if ( RHSd > VERY_SMALL_NUM ) { // Get the digit RHSd = RHSd * 10.0; digitll = ( long long ) RHSd; digit = ( Char ) (( Char ) ( digitll ) + '0'); // Stuff it in the destination array len++, *dstP++ = digit; RHSd = RHSd - ( double ) digitll; }// No significant digit, zero fill out to maxLen else if ( len < maxLen ) { len++, *dstP++ = '0'; } else // Zero filled to maxLen, get out of here. We're done. { break; } }// Terminate the result. *dstP++ = '\0'; } // If the number is too large for displaying, fill it with// overflow indicators and cut it off so it fits. len = ( UInt8 ) StrLen ( altDstP ); if ( len > maxLen ) { UInt8 i; for ( i = 0; i < maxLen; i++ ) { // Only convert digits, leave punctuation alone if (( altDstP [ i ] >= '0' ) && ( altDstP [ i ] <= '9' )) { altDstP [ i ] = '>'; } } // Terminate the string at the proper length altDstP [ maxLen ] = '\0';} }#pragma mark ----------------/************************************ * FUNCTION: CheckValidNumChar * * DESCRIPTION: Check for valid numeric characters. * * RETURNED: true if the character was handled ************************************/static Boolean CheckValidNumChar // ( out ) handled?( FieldPtr fldP, // ( in ) pointer to the current field UInt8 key, // ( in ) the current keystroke UInt8 precision // ( in ) precision of current numeric field){ Boolean handled = false; Char * hyphen = "-"; Char * textP = FldGetTextPtr ( fldP );// Allow a hyphen if in the first character position and there isn't one. if ( key == '-' && FldGetInsPtPosition ( fldP ) == 0 ) { if ( ! textP || StrStr ( textP, hyphen) == NULL ) { FldInsert ( fldP, hyphen, 1 ); handled = true; } } // Filter out decimal separator if an integer ( precision == 0 ) else if ( key == gDSep && precision == 0 ) { handled = true; } // Don't let the user enter more than MAX_DIGITS digits on either side of the decimal point else if ( TxtCharIsDigit ( key ) && textP ) { UInt8 LHSLen, RHSLen = 0; UInt16 insertPt = FldGetInsPtPosition ( fldP ); LHSLen = ( UInt8 ) StrLen ( textP ); // Get right and left-hand side lengths of the current string if ( StrChr ( textP, gDSep )) { RHSLen = ( UInt8 ) ( StrLen ( textP ) - (( UInt32 ) StrChr ( textP, gDSep ) - ( UInt32 ) ( textP )) - 1 ); LHSLen = ( UInt8 ) ( LHSLen - RHSLen - 1 ); } // Ignore excess digits on left-hand side if ( insertPt <= LHSLen && LHSLen >= MAX_LHS_DIGITS ) { handled = true; } // Ignore excess digits on right-hand side else if ( insertPt > LHSLen && RHSLen >= MAX_RHS_DIGITS ) { handled = true; } } return handled;}/*********************************************************************** * FUNCTION: DisplayNumber * * DESCRIPTION: Fetch a user-entered number from one field, convert * it to a double precision number, convert the double to * a fully-formatted displayable string, and assign it
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -