Edit Custom KeyHandler (Sample)

From SEGGER Wiki
Jump to: navigation, search
EDIT_Custom_KeyHandler.c
IP address entered to the EDIT with custom key handling.
File(s) required
  • EDIT_Custom_KeyHandler.c
Runs in simulation Yes
Runs on target Yes
Download EDIT_Custom_KeyHandler.c

This sample demonstrates how a custom key handling function can be set to an EDIT widget. This can be utilized for EDIT widgets that should only accept certain formatted strings.

In this example, the purpose of the EDIT widget is for entering IP addresses. Therefore, the custom key handling function will check if the entered IP address is in the correct format and automatically add dots.

Demo


Code

/*********************************************************************
*                    SEGGER Microcontroller GmbH                     *
*        Solutions for real time microcontroller applications        *
**********************************************************************
*                                                                    *
*        (c) 1996 - 2022  SEGGER Microcontroller GmbH                *
*                                                                    *
*        Internet: www.segger.com    Support:  support@segger.com    *
*                                                                    *
**********************************************************************

** emWin V6.26 - Graphical user interface for embedded applications **
emWin is protected by international copyright laws.   Knowledge of the
source code may not be used to write a similar product.  This file may
only  be used  in accordance  with  a license  and should  not be  re-
distributed in any way. We appreciate your understanding and fairness.
----------------------------------------------------------------------
File        : EDIT_Custom_KeyHandler.c
Purpose     : This sample demonstrates how a custom key handler can be
              set to an EDIT widget. In this example, the input of the
              EDIT is checked to be a valid IP address.
Requirements: WindowManager - (x)
              MemoryDevices - ( )
              AntiAliasing  - ( )
              VNC-Server    - ( )
              PNG-Library   - ( )
              TrueTypeFonts - ( )
Wiki link   : https://wiki.segger.com/EDIT_Custom_KeyHandler_%28Sample%29
---------------------------END-OF-HEADER------------------------------
*/

#include "DIALOG.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*********************************************************************
*
*       Static code
*
**********************************************************************
*/
/*********************************************************************
*
*       _IsNumber
*/
static U8 _IsNumber(char c) {
  return ((c >= '0') && (c <= '9')) ? 1 : 0;
}

/*********************************************************************
*
*       _AddKey
*/
static void _AddKey(EDIT_Handle hObj, int Key) {
  char * pBuffer;
  int    NumChars;
  int    NumBytes;
  int    i;
  int    NumDots;
  char   Prev;
  int    LastDot;
  char * pNumber;
  int    Num;

  //
  // We want the default behavior for these keys.
  //
  switch (Key) {
  case GUI_KEY_HOME:
  case GUI_KEY_END:
  case GUI_KEY_LEFT:
  case GUI_KEY_RIGHT:
  case GUI_KEY_BACKSPACE:
    //
    // Key handler has to be temporarily NULLed to prevent an endless recursion.
    //
    EDIT_SetpfAddKeyEx(hObj, 0);
    EDIT_AddKey(hObj, Key);
    EDIT_SetpfAddKeyEx(hObj, _AddKey);
    return;
  }
  //
  // We want to skip all other keys that are not numbers or dots.
  // 
  if (!((_IsNumber(Key)) || (Key == '.'))) {
    return;
  }
  //
  // Check if limit has been reached.
  //
  NumChars = EDIT_GetNumChars(hObj);
  if (NumChars == 15) {
    return;
  }
  //
  // Alloc buffer with a little extra space and retrieve the current EDIT text.
  //
  NumBytes = NumChars + 6;
  pBuffer  = (char *)malloc(NumBytes);
  EDIT_GetText(hObj, pBuffer, NumBytes);
  //
  // Count the dots to see if the limit has been reached
  //
  i = NumDots = 0;
  LastDot = 0;
  while (*(pBuffer + i)) {
    if (*(pBuffer + i) == '.') {
      NumDots++;
      LastDot = i;
    }
    i++;
  }
  //
  // If last number has 3 digits
  //
  if ((NumDots == 3) && (LastDot == (NumChars - 4))) {
    free(pBuffer);
    return;
  }
  //
  // Check if maximum number of dots has been reached.
  // 
  if (Key == '.') {
    if (NumDots == 3) {
      free(pBuffer);
      return;
    }
  }
  //
  // Add dot if previous character is a number
  // 
  if (Key == '.') {
    Prev = *(pBuffer + (NumChars - 1));
    if ((Prev != '.') && (_IsNumber(Prev))) {
      *(pBuffer + NumChars++) = Key;
    }
  }
  //
  // Add number
  //
  if (_IsNumber(Key)) {
    *(pBuffer + NumChars++) = Key;
  }
  //
  // Zero-terminate string
  //
  *(pBuffer + NumChars) = 0;
  //
  // Get position of last dot
  //
  i = NumChars;
  LastDot = -1;
  do {
    if (*(pBuffer + i) == '.') {
      LastDot = i;
      break;
    }
    i--;
  } while (i > 0);
  pNumber = pBuffer;
  if (LastDot != -1) {
    pNumber += LastDot + 1;
  }
  Num = atoi(pNumber);
  if (Num > 255) {
    memcpy(pNumber, "255",  4);
  }
  //
  // Add dot if necessary.
  //
  if ((Num > 100) && (NumDots < 3)) {
    strcat(pNumber, ".");
    NumChars++;
  }
  //
  // Copy the new text buffer to the EDIT and free it
  //
  EDIT_SetText(hObj, (const char *)pBuffer);
  free(pBuffer);
  //
  // Update cursor position
  //
  EDIT_SetCursorAtChar(hObj, NumChars);
}

/*********************************************************************
*
*       _cbBk
*/
static void _cbBk(WM_MESSAGE * pMsg) {
  switch (pMsg->MsgId) {
  case WM_PAINT:
    GUI_SetBkColor(GUI_WHITE);
    GUI_Clear();
    GUI_SetColor(GUI_BLACK);
    GUI_SetFont(&GUI_Font16_1);
    GUI_DispStringAt("Enter IP address:", 10, 10);
    break;
  default:
    WM_DefaultProc(pMsg);
  }
}

/*********************************************************************
*
*       Public code
*
**********************************************************************
*/
/*********************************************************************
*
*       MainTask
*/
void MainTask(void) {
  WM_HWIN hEdit;
  WM_HWIN hKeyboard;

  //
  // Init GUI
  //
  GUI_Init();
  WM_SetCallback(WM_HBKWIN, _cbBk);
  //
  // Create EDIT widget
  //
  hEdit = EDIT_CreateEx(10, 30, 100, 25, WM_HBKWIN, WM_CF_SHOW, 0, GUI_ID_EDIT0, 100);
  //
  // Set custom key handling function
  //
  EDIT_SetpfAddKeyEx(hEdit, _AddKey);
  //
  // Create numpad for entering
  //
  hKeyboard = KEYBOARD_CreateUser(150, 10, 150, 200, WM_HBKWIN, WM_CF_SHOW, 0, &KEYBOARD_NUMPAD, GUI_ID_KEYBOARD0, 0);

  while (1) {
    GUI_Delay(100);
  }
}

/*************************** End of file ****************************/