void CHexCalculator::handleActionEvent()

in graphics/nxwm/src/chexcalculator.cxx [698:941]


void CHexCalculator::handleActionEvent(const NXWidgets::CWidgetEventArgs &e)
{
  // A button should now be clicked

  int column;
  int row;

  if (m_keypad->isButtonClicked(column, row))
    {
      // Handle the key according to its type

      int index = row * NXWM_HEXCALCULATOR_NCOLUMNS + column;

      // First, make sure that the keypress is valid in this mode

      if ((m_hexMode && !g_keyDesc[index].hexMode) ||
          (!m_hexMode && !g_keyDesc[index].decMode))
        {
          // Ignore the key in this mode

          return;
        }

      // Process the keypress

      bool result = false;
      switch (g_keyDesc[index].keyType)
        {
          // Values: {0-9, A-F}

          case KEY_VALUE:       // Key is a value
            {
              // If the accumulator current holds the result of a previous
              // operation, then start fresh

              if (m_result)
                {
                  m_accum = (uint64_t)g_keyDesc[index].value;
                }

              // Otherwise, add the new value to the accumulator.  The way
              // in which it is added depends on the mode

              else if (m_hexMode)
                {
                  m_accum <<= 4;
                  m_accum |= (uint64_t)g_keyDesc[index].value;
                }
              else
                {
                  m_accum *= 10;
                  m_accum += (uint64_t)g_keyDesc[index].value;
                }
              updateText();
            }
            break;

          // Unary operators

          case KEY_NOT:         // 1's complement
            {
              m_accum = ~m_accum;
              updateText();
            }
            break;

          case KEY_NEGATE:      // 2's complement
            {
              m_accum = -m_accum;
              updateText();
            }
            break;

          // Low precedence Binary operators

          case KEY_XOR:         // Exclusive OR
          case KEY_OR:          // Bit-wise OR
          case KEY_MINUS:       // Subtraction
          case KEY_PLUS:        // Additions
            {
              // Is there a high precedence operation?

              if (m_high.operation != (uint8_t)KEY_NONE)
                {
                  m_accum          = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum);
                  m_high.operation = (uint8_t)KEY_NONE;
                  m_high.value     = 0;
                }

              // Is there a pending low precedence operation?

              if (m_low.operation != (uint8_t)KEY_NONE)
                {
                  m_accum  = evaluateBinaryOperation(m_low.operation, m_low.value, m_accum);
                }

              // Save the new low precedence operation

              m_low.operation = (uint8_t) g_keyDesc[index].keyType;
              m_low.value     = m_accum;

              // Update the display with the value in the accumulator, but
              // then clear the accumulator in preparation for the next input

              updateText();
              m_accum = 0;
            }
            break;

          // High precedence Binary operators

          case KEY_DIVIDE:      // Division
          case KEY_RSH:         // Right shift
          case KEY_LSH:         // Left shift
          case KEY_MULTIPLY:    // Multiplication
          case KEY_AND:         // Bit-wise AND
            {
              // Is there a high precedence operation?

              if (m_high.operation != (uint8_t)KEY_NONE)
                {
                  m_accum = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum);
                }

              // Save the new high precedence operation

              m_high.operation = (uint8_t) g_keyDesc[index].keyType;
              m_high.value     = m_accum;

              // Update the display with the value in the accumulator, but
              // then clear the accumulator in preparation for the next input

              updateText();
              m_accum = 0;
            }
            break;

          // Special operations

          case KEY_EQUAL:       // Equal/Enter key
            {
              // Is there a high precedence operation?

              if (m_high.operation != (uint8_t)KEY_NONE)
                {
                  m_accum          = evaluateBinaryOperation(m_high.operation, m_high.value, m_accum);
                  m_high.operation = (uint8_t)KEY_NONE;
                  m_high.value     = 0;
                }

              // Is there a pending low precedence operation?

              if (m_low.operation != (uint8_t)KEY_NONE)
                {
                  m_accum         = evaluateBinaryOperation(m_low.operation, m_low.value, m_accum);
                  m_low.operation = (uint8_t)KEY_NONE;
                  m_low.value     = 0;
                }

              // Update the display with the value in the accumulator.  Flag that
              // this is a result meaning that (1) it can be used as an accumulator
              // for the next operation, but new input values cannot be appended to it.

              updateText();
              result = true;
            }
            break;

          case KEY_DECIMAL:     // Decimal mode
            {
              if (m_hexMode)
                {
                  m_hexMode = false;
                  labelKeypad();
                  updateText();
                }
            }
            break;

          case KEY_HEXADECIMAL: // Hexadecimal mode
            {
              if (!m_hexMode)
                {
                  m_hexMode = true;
                  labelKeypad();
                  updateText();
                }
            }
            break;

          case KEY_MRECALL:   // Recall from memory
            {
               m_accum = m_memory;
               updateText();
            }
            break;

          case KEY_MPLUS:     // Add to memory
            {
               m_memory += m_accum;
            }
            break;

          case KEY_MMINUS:    // Subtract from memory
            {
               m_memory -= m_accum;
            }
            break;

          case KEY_MCLR:      // Clear memory
            {
               m_memory = 0;
            }
            break;

          case KEY_CLRENTRY:  // Clear entry
            {
               m_accum = 0;
               updateText();
            }
            break;

          case KEY_CLR:       // Clear all
            {
               m_accum          = 0;
               m_high.operation = (uint8_t)KEY_NONE;
               m_high.value     = 0;
               m_low.operation  = (uint8_t)KEY_NONE;
               m_low.value      = 0;
               updateText();
            }
            break;

          case KEY_NONE:
          default:
            gerr("ERROR: Invalid key type %d\n", g_keyDesc[index].keyType);
            break;
        }

      // Remember if the accumulator contains a special reault

      m_result = result;
    }
}