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.
		
		
		
		
		
			
		
			
				
					460 lines
				
				12 KiB
			
		
		
			
		
	
	
					460 lines
				
				12 KiB
			| 
								 
											7 years ago
										 
									 | 
							
								#include "doogle999.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static unsigned char inputLocation = 0; // Current index in text input
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								static double calc(const char input[CALC_BUFFER_SIZE +1]) // Finds value of input char array, relatively small and fast I think
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  char inputToken[CALC_BUFFER_SIZE + 1]; // Input buffer, used when a single token (generally a number) takes up more
							 | 
						||
| 
								 | 
							
								  unsigned char inputTokenLocation = 0, inputLocation = 0; // Keep track of indices
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  struct Token tokens[CALC_BUFFER_SIZE + 1]; // Input, converted to tokens, one extra large to accomodate for possible negative sign then open parenthesis as first character
							 | 
						||
| 
								 | 
							
								  unsigned char tokenCount = 0; // Keep track of index
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool dashAsMinus = false; // Kind of a hacky solution to determining whether to treat a dash as a minus sign or a negative sign
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  while(inputLocation < CALC_BUFFER_SIZE + 1)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    char digit = input[inputLocation];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(inputLocation == 0 && input[inputLocation] == CALC_CHAR_SUB && input[inputLocation + 1] == CALC_CHAR_BEG)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      tokens[tokenCount].raw.num = 0;
							 | 
						||
| 
								 | 
							
								      tokens[tokenCount].isNum = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      tokenCount++;
							 | 
						||
| 
								 | 
							
								      dashAsMinus = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if ((digit >= '0' && digit <= '9') || /* valid digit */
							 | 
						||
| 
								 | 
							
								        (inputTokenLocation != 0 && input[inputLocation] == CALC_CHAR_DEC) || /* valid floating point */
							 | 
						||
| 
								 | 
							
								        (!dashAsMinus && inputTokenLocation == 0 && input[inputLocation] == CALC_CHAR_SUB)) /* - is negative sign */
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      inputToken[inputTokenLocation] = input[inputLocation];
							 | 
						||
| 
								 | 
							
								      inputTokenLocation++;
							 | 
						||
| 
								 | 
							
								      inputLocation++;
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(inputTokenLocation != 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // sscanf(inputToken, "%lf", &tokens[tokenCount].raw.num); // I would like to use sscanf here, but the small version of stdio.h on the chip doesn't allow sscanf or its sister functions to be used to process floats
							 | 
						||
| 
								 | 
							
								      tokens[tokenCount].raw.num = atof(inputToken);
							 | 
						||
| 
								 | 
							
								      tokens[tokenCount].isNum = true;
							 | 
						||
| 
								 | 
							
								      for(unsigned char i = 0; i < inputTokenLocation + 1; i++)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        inputToken[i] = '\0';
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      inputTokenLocation = 0;
							 | 
						||
| 
								 | 
							
								      tokenCount++;
							 | 
						||
| 
								 | 
							
								      dashAsMinus = true;
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    /* inputTokenLocation == 0 */
							 | 
						||
| 
								 | 
							
								    tokens[tokenCount].isNum = false;
							 | 
						||
| 
								 | 
							
								    tokens[tokenCount].raw.op.c = input[inputLocation];
							 | 
						||
| 
								 | 
							
								    tokens[tokenCount].raw.op.priority = 0;
							 | 
						||
| 
								 | 
							
								    tokens[tokenCount].raw.op.ltr = true;
							 | 
						||
| 
								 | 
							
								    dashAsMinus = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    switch(input[inputLocation])
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_BEG:
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_END:
							 | 
						||
| 
								 | 
							
								        dashAsMinus = true;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_ADD:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.priority = CALC_PRIO_ADD;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_SUB:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.priority = CALC_PRIO_SUB;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_MUL:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.priority = CALC_PRIO_MUL;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_DIV:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.priority = CALC_PRIO_DIV;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_EXP:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.priority = CALC_PRIO_EXP;
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.op.ltr = false;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_SIN:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_COS:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_TAN:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_ASN:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_ACS:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_ATN:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_LGE:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_LOG:
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_SQT:
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_EUL:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].isNum = true;
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.num = CALC_VALU_EUL;
							 | 
						||
| 
								 | 
							
								        dashAsMinus = true;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_PI:
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].isNum = true;
							 | 
						||
| 
								 | 
							
								        tokens[tokenCount].raw.num = CALC_VALU_PI;
							 | 
						||
| 
								 | 
							
								        dashAsMinus = true;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case '\0':
							 | 
						||
| 
								 | 
							
								        tokenCount--;
							 | 
						||
| 
								 | 
							
								        inputLocation = CALC_BUFFER_SIZE;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
								        tokenCount--;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    tokenCount++;
							 | 
						||
| 
								 | 
							
								    inputLocation++;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  struct Token output[CALC_BUFFER_SIZE + 1]; // Final output tokens before evaluation
							 | 
						||
| 
								 | 
							
								  struct Token opstack[CALC_BUFFER_SIZE + 1]; // Stack of operators
							 | 
						||
| 
								 | 
							
								  unsigned char outputLocation = 0, opstackLocation = 0; // Keep track of indices
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  unsigned char numBrackets = 0; // The number of parenthesis
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(unsigned char i = 0; i < tokenCount; i++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if(tokens[i].isNum)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      output[outputLocation] = tokens[i];
							 | 
						||
| 
								 | 
							
								      outputLocation++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else if(tokens[i].raw.op.c == CALC_CHAR_BEG)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      opstack[opstackLocation] = tokens[i];
							 | 
						||
| 
								 | 
							
								      opstackLocation++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else if(tokens[i].raw.op.c == CALC_CHAR_END)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      while(opstack[opstackLocation - 1].raw.op.c != CALC_CHAR_BEG)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        output[outputLocation] = opstack[opstackLocation - 1];
							 | 
						||
| 
								 | 
							
								        outputLocation++;
							 | 
						||
| 
								 | 
							
								        opstackLocation--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      opstackLocation--;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      numBrackets += 2;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else if(tokens[i].raw.op.priority == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      opstack[opstackLocation] = tokens[i];
							 | 
						||
| 
								 | 
							
								      opstackLocation++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      while(opstackLocation != 0
							 | 
						||
| 
								 | 
							
								        && (opstack[opstackLocation - 1].raw.op.priority == 0
							 | 
						||
| 
								 | 
							
								          || tokens[i].raw.op.priority < opstack[opstackLocation - 1].raw.op.priority
							 | 
						||
| 
								 | 
							
								          || (tokens[i].raw.op.priority == opstack[opstackLocation - 1].raw.op.priority && opstack[opstackLocation - 1].raw.op.ltr))
							 | 
						||
| 
								 | 
							
								        && opstack[opstackLocation - 1].raw.op.c != CALC_CHAR_BEG)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        output[outputLocation] = opstack[opstackLocation - 1];
							 | 
						||
| 
								 | 
							
								        outputLocation++;
							 | 
						||
| 
								 | 
							
								        opstackLocation--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      opstack[opstackLocation] = tokens[i];
							 | 
						||
| 
								 | 
							
								      opstackLocation++;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  tokenCount -= numBrackets;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(signed char i = opstackLocation - 1; i >= 0; i--)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    output[outputLocation] = opstack[i];
							 | 
						||
| 
								 | 
							
								    outputLocation++;
							 | 
						||
| 
								 | 
							
								    opstackLocation--;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  double answer[CALC_BUFFER_SIZE];
							 | 
						||
| 
								 | 
							
								  unsigned char answerLocation = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for(unsigned char i = 0; i < tokenCount; i++)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if(output[i].isNum)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      answer[answerLocation] = output[i].raw.num;
							 | 
						||
| 
								 | 
							
								      answerLocation++;
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if(output[i].raw.op.priority == 0)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (answerLocation < 1) { /* not handled here -- ERROR? */ } else
							 | 
						||
| 
								 | 
							
								      if(answerLocation >= 1)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        double (*op)(double);
							 | 
						||
| 
								 | 
							
								        switch(output[i].raw.op.c)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_SIN:
							 | 
						||
| 
								 | 
							
								          op = sin;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_COS:
							 | 
						||
| 
								 | 
							
								          op = cos;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_TAN:
							 | 
						||
| 
								 | 
							
								          op = tan;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_ASN:
							 | 
						||
| 
								 | 
							
								          op = asin;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_ACS:
							 | 
						||
| 
								 | 
							
								          op = acos;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_ATN:
							 | 
						||
| 
								 | 
							
								          op = atan;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_LGE:
							 | 
						||
| 
								 | 
							
								          op = log;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_LOG:
							 | 
						||
| 
								 | 
							
								          op = log10;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        case CALC_CHAR_SQT:
							 | 
						||
| 
								 | 
							
								          op = sqrt;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        default:
							 | 
						||
| 
								 | 
							
								          continue; /* invalid input */
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 1] = op(answer[answerLocation - 1]);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /* priority != 0 */
							 | 
						||
| 
								 | 
							
								    else if(answerLocation >= 2)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      switch(output[i].raw.op.c)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_ADD:
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 2] += answer[answerLocation - 1];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_SUB:
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 2] -= answer[answerLocation - 1];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_MUL:
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 2] *= answer[answerLocation - 1];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_DIV:
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 2] /= answer[answerLocation - 1];
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case CALC_CHAR_EXP:
							 | 
						||
| 
								 | 
							
								        answer[answerLocation - 2] = pow(answer[answerLocation - 2], answer[answerLocation - 1]);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      answerLocation--;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return answer[0];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * @returns  0 when nothing should happen and QMK should work as usual
							 | 
						||
| 
								 | 
							
								 * @returns -1 when invalid input was given, QMK should ignore it
							 | 
						||
| 
								 | 
							
								 * @returns -2 when BSP should be done
							 | 
						||
| 
								 | 
							
								 * @returns -3 when CALC should be done
							 | 
						||
| 
								 | 
							
								 * @returns -4 when ENDCALC should be done
							 | 
						||
| 
								 | 
							
								 * @returns positive value of CALC_* when normal input was processed
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								static int process_input(const uint16_t keycode, const uint8_t mods, const keyevent_t event)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  /* handle even when no key was pressed */
							 | 
						||
| 
								 | 
							
								  if(!event.pressed)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    switch(keycode)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      /* QMK should handle those */
							 | 
						||
| 
								 | 
							
								      case KC_RSFT:
							 | 
						||
| 
								 | 
							
								      case KC_LSFT:
							 | 
						||
| 
								 | 
							
								        return 0;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    /* ??? ignore */
							 | 
						||
| 
								 | 
							
								    return -1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* when shift key is pressed handle characters differently */
							 | 
						||
| 
								 | 
							
								  char characterPressed;
							 | 
						||
| 
								 | 
							
								  if((get_mods() & MODS_SHIFT_MASK))
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    switch(keycode)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      case KC_9:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_BEG;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_0:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_END;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_EQUAL:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_ADD;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_KP_PLUS:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_ADD;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_6:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_EXP;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_8:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_MUL;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_KP_ASTERISK:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_MUL;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_S:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_ASN;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_C:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_ACS;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_T:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_ATN;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      case KC_L:
							 | 
						||
| 
								 | 
							
								        characterPressed = CALC_CHAR_LOG;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
								        return -1;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return characterPressed;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* normal key handling:  shift not pressed */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* digits */
							 | 
						||
| 
								 | 
							
								  if (keycode == KC_KP_0 || keycode == KC_0) {
							 | 
						||
| 
								 | 
							
								    return '0';
							 | 
						||
| 
								 | 
							
								  } else if (keycode >= KC_KP_1 && keycode <= KC_KP_9) {
							 | 
						||
| 
								 | 
							
								    return keycode - KC_KP_1 +1 + '0';
							 | 
						||
| 
								 | 
							
								  } else if (keycode >= KC_1 && keycode <= KC_9) {
							 | 
						||
| 
								 | 
							
								    return keycode - KC_1 +1 + '0';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* other tokens */
							 | 
						||
| 
								 | 
							
								  switch (keycode) {
							 | 
						||
| 
								 | 
							
								    case KC_MINUS:
							 | 
						||
| 
								 | 
							
								    case KC_KP_MINUS:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_SUB;
							 | 
						||
| 
								 | 
							
								    case KC_SLASH:
							 | 
						||
| 
								 | 
							
								    case KC_KP_SLASH:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_DIV;
							 | 
						||
| 
								 | 
							
								    case KC_S:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_SIN;
							 | 
						||
| 
								 | 
							
								    case KC_C:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_COS;
							 | 
						||
| 
								 | 
							
								    case KC_T:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_TAN;
							 | 
						||
| 
								 | 
							
								    case KC_Q:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_SQT;
							 | 
						||
| 
								 | 
							
								    case KC_L:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_LGE;
							 | 
						||
| 
								 | 
							
								    case KC_DOT:
							 | 
						||
| 
								 | 
							
								    case KC_KP_DOT:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_DEC;
							 | 
						||
| 
								 | 
							
								    case KC_P:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_PI;
							 | 
						||
| 
								 | 
							
								    case KC_E:
							 | 
						||
| 
								 | 
							
								      return characterPressed = CALC_CHAR_EUL;
							 | 
						||
| 
								 | 
							
								    case KC_BSPC:
							 | 
						||
| 
								 | 
							
								      return -2;
							 | 
						||
| 
								 | 
							
								    case KC_RSFT:
							 | 
						||
| 
								 | 
							
								      return 0;
							 | 
						||
| 
								 | 
							
								    case KC_LSFT:
							 | 
						||
| 
								 | 
							
								      return 0;
							 | 
						||
| 
								 | 
							
								    case CALC:
							 | 
						||
| 
								 | 
							
								      return -3;
							 | 
						||
| 
								 | 
							
								    case ENDCALC:
							 | 
						||
| 
								 | 
							
								      return -4;
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      return -1;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool process_record_user(uint16_t keycode, keyrecord_t* record)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									static char text[CALC_BUFFER_SIZE + 1]; // Used to store input and then output when ready to print
							 | 
						||
| 
								 | 
							
									static char backspaceText[CALC_BUFFER_SIZE + 1]; // Pretty dumb waste of memory because only backspace characters, used with send_string to backspace and remove input
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if((biton32(layer_state) == CALC_LAYER && CALC_FORCE_NUM_LOCK_INSIDE_CALC) || (biton32(layer_state) != CALC_LAYER && CALC_FORCE_NUM_LOCK_OUTSIDE_CALC))
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										bool numpadKeyPressed = record->event.pressed &&
							 | 
						||
| 
								 | 
							
											!(get_mods() & MODS_SHIFT_MASK) &&
							 | 
						||
| 
								 | 
							
											/* KC_KP_1, KC_KP_2, ..., KC_KP_0, KC_KP_DOT */
							 | 
						||
| 
								 | 
							
											(keycode >= KC_KP_1 && keycode <= KC_KP_DOT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										if(numpadKeyPressed && !(host_keyboard_leds() & (1 << USB_LED_NUM_LOCK)))
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											add_key(KC_NLCK);
							 | 
						||
| 
								 | 
							
											send_keyboard_report();
							 | 
						||
| 
								 | 
							
											del_key(KC_NLCK);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(biton32(layer_state) != CALC_LAYER) { return true; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int action = process_input(keycode, get_mods(), record->event);
							 | 
						||
| 
								 | 
							
									switch(action)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
									case 0:
							 | 
						||
| 
								 | 
							
										return true;
							 | 
						||
| 
								 | 
							
									case -1:
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									case -2:
							 | 
						||
| 
								 | 
							
										if(inputLocation > 0)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											inputLocation--;
							 | 
						||
| 
								 | 
							
											text[inputLocation] = '\0';
							 | 
						||
| 
								 | 
							
											backspaceText[0] = (char)8;
							 | 
						||
| 
								 | 
							
											backspaceText[1] = '\0';
							 | 
						||
| 
								 | 
							
											send_string(backspaceText);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									case -3:
							 | 
						||
| 
								 | 
							
										for(int i = 0; i < inputLocation; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											backspaceText[i] = (char)8;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										send_string(backspaceText);
							 | 
						||
| 
								 | 
							
										dtostrf(calc(text), CALC_PRINT_SIZE, CALC_PRINT_SIZE, text);
							 | 
						||
| 
								 | 
							
										send_string(text);
							 | 
						||
| 
								 | 
							
										for(unsigned char i = 0; i < CALC_BUFFER_SIZE; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											text[i] = '\0';
							 | 
						||
| 
								 | 
							
											backspaceText[i] = '\0';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										inputLocation = 0;
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									case -4:
							 | 
						||
| 
								 | 
							
										for(unsigned char i = 0; i < CALC_BUFFER_SIZE; i++)
							 | 
						||
| 
								 | 
							
										{
							 | 
						||
| 
								 | 
							
											text[i] = '\0';
							 | 
						||
| 
								 | 
							
											backspaceText[i] = '\0';
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										inputLocation = 0;
							 | 
						||
| 
								 | 
							
										layer_off(CALC_LAYER);
							 | 
						||
| 
								 | 
							
										return false;
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									char characterPressed = (char)action;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if(inputLocation < CALC_BUFFER_SIZE)
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										text[inputLocation] = characterPressed;
							 | 
						||
| 
								 | 
							
										inputLocation++;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										char characterToSend[2];
							 | 
						||
| 
								 | 
							
										characterToSend[0] = characterPressed;
							 | 
						||
| 
								 | 
							
										characterToSend[1] = '\0';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										send_string(characterToSend);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return false;
							 | 
						||
| 
								 | 
							
								}
							 |