From 8a8f887d6bb16750ce3b088d84465ef1210930f8 Mon Sep 17 00:00:00 2001 From: franki Date: Tue, 22 Nov 2022 16:33:41 +0800 Subject: [PATCH 1/1] =?utf8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90?= =?utf8?q?=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- Makefile | 52 + bak/sgi_data.cpp | 237 +++++ bak/sgi_data.h | 51 + cabinet/cabinet | Bin 0 -> 278476 bytes drivers/mfcard/.tmp_versions/mfcard.mod | 2 + drivers/mfcard/Makefile | 14 + drivers/mfcard/mfcard.c | 466 +++++++++ drivers/mfcard/mfcard.h | 65 ++ drivers/mfcard/mfcard.ko | Bin 0 -> 103128 bytes obj/crc.o | Bin 0 -> 2324 bytes obj/finger_intf.o | Bin 0 -> 5872 bytes obj/fingerprint.o | Bin 0 -> 4360 bytes obj/fm_alarm.o | Bin 0 -> 9404 bytes obj/fm_alarm_pwd.o | Bin 0 -> 11060 bytes obj/fm_borrow_card_manager.o | Bin 0 -> 11032 bytes obj/fm_borrow_card_user.o | Bin 0 -> 11092 bytes obj/fm_borrow_fpr_manager.o | Bin 0 -> 12288 bytes obj/fm_borrow_fpr_user.o | Bin 0 -> 12380 bytes obj/fm_borrow_photo_user.o | Bin 0 -> 12084 bytes obj/fm_borrow_pwd_manager.o | Bin 0 -> 11012 bytes obj/fm_borrow_pwd_user.o | Bin 0 -> 11124 bytes obj/fm_borrow_unlock.o | Bin 0 -> 11552 bytes obj/fm_box_manage.o | Bin 0 -> 10552 bytes obj/fm_chpwd.o | Bin 0 -> 12456 bytes obj/fm_download.o | Bin 0 -> 12444 bytes obj/fm_info_choice.o | Bin 0 -> 9400 bytes obj/fm_info_register.o | Bin 0 -> 10988 bytes obj/fm_info_stat.o | Bin 0 -> 10760 bytes obj/fm_level.o | Bin 0 -> 10084 bytes obj/fm_log_alarm.o | Bin 0 -> 11856 bytes obj/fm_log_borrow.o | Bin 0 -> 12280 bytes obj/fm_log_main.o | Bin 0 -> 10776 bytes obj/fm_log_manager.o | Bin 0 -> 12164 bytes obj/fm_log_return.o | Bin 0 -> 12276 bytes obj/fm_log_system.o | Bin 0 -> 12156 bytes obj/fm_main.o | Bin 0 -> 11540 bytes obj/fm_menu.o | Bin 0 -> 10576 bytes obj/fm_menu_pwd.o | Bin 0 -> 10968 bytes obj/fm_mon_setting.o | Bin 0 -> 12776 bytes obj/fm_reg_box.o | Bin 0 -> 13624 bytes obj/fm_reg_bullet.o | Bin 0 -> 11976 bytes obj/fm_reg_fpr1_1.o | Bin 0 -> 10228 bytes obj/fm_reg_fpr1_2.o | Bin 0 -> 10180 bytes obj/fm_reg_fpr1_3.o | Bin 0 -> 10288 bytes obj/fm_reg_gun.o | Bin 0 -> 17112 bytes obj/fm_reg_person.o | Bin 0 -> 19448 bytes obj/fm_reg_photo.o | Bin 0 -> 9776 bytes obj/fm_reg_pwd.o | Bin 0 -> 11276 bytes obj/fm_reg_unit.o | Bin 0 -> 12336 bytes obj/fm_return_card_manager.o | Bin 0 -> 10884 bytes obj/fm_return_card_user.o | Bin 0 -> 10944 bytes obj/fm_return_fpr_manager.o | Bin 0 -> 12116 bytes obj/fm_return_fpr_user.o | Bin 0 -> 12168 bytes obj/fm_return_photo_user.o | Bin 0 -> 11344 bytes obj/fm_return_pwd_manager.o | Bin 0 -> 11036 bytes obj/fm_return_pwd_user.o | Bin 0 -> 11012 bytes obj/fm_return_unlock.o | Bin 0 -> 12088 bytes obj/fm_safecheck.o | Bin 0 -> 11604 bytes obj/fm_stat_box.o | Bin 0 -> 11808 bytes obj/fm_stat_bullet.o | Bin 0 -> 9588 bytes obj/fm_stat_gun.o | Bin 0 -> 12368 bytes obj/fm_stat_person.o | Bin 0 -> 12508 bytes obj/fm_stat_unit.o | Bin 0 -> 10848 bytes obj/fm_system.o | Bin 0 -> 10600 bytes obj/fm_timing.o | Bin 0 -> 13772 bytes obj/fm_unlock.o | Bin 0 -> 9472 bytes obj/fm_unlock_pwd.o | Bin 0 -> 11180 bytes obj/fm_user_level.o | Bin 0 -> 13908 bytes obj/main.o | Bin 0 -> 3292 bytes obj/monitor.o | Bin 0 -> 15828 bytes obj/net.o | Bin 0 -> 18780 bytes obj/pinyin.o | Bin 0 -> 42380 bytes obj/raw_i2c.o | Bin 0 -> 3496 bytes obj/sgi_base.o | Bin 0 -> 16008 bytes obj/sgi_base_box.o | Bin 0 -> 3460 bytes obj/sgi_base_button.o | Bin 0 -> 3012 bytes obj/sgi_base_check.o | Bin 0 -> 2560 bytes obj/sgi_base_edit.o | Bin 0 -> 3612 bytes obj/sgi_base_form.o | Bin 0 -> 3800 bytes obj/sgi_base_grid.o | Bin 0 -> 3624 bytes obj/sgi_base_ime.o | Bin 0 -> 5496 bytes obj/sgi_base_indicator.o | Bin 0 -> 1948 bytes obj/sgi_base_label.o | Bin 0 -> 2656 bytes obj/sgi_base_msgbox.o | Bin 0 -> 3564 bytes obj/sgi_base_picture.o | Bin 0 -> 2348 bytes obj/sgi_base_radio.o | Bin 0 -> 2620 bytes obj/sgi_base_updown.o | Bin 0 -> 3808 bytes obj/sgi_base_window.o | Bin 0 -> 2444 bytes obj/sgi_data.o | Bin 0 -> 23684 bytes obj/sgi_form_manage.o | Bin 0 -> 13036 bytes obj/sgi_ime.o | Bin 0 -> 3876 bytes obj/sgi_log.o | Bin 0 -> 13108 bytes obj/sgi_msgbox.o | Bin 0 -> 1852 bytes obj/sgi_resource.o | Bin 0 -> 10028 bytes obj/sgi_string.o | Bin 0 -> 2480 bytes obj/uart.o | Bin 0 -> 2924 bytes obj/udisk.o | Bin 0 -> 3064 bytes src/crc.cpp | 49 + src/finger_intf.cpp | 402 ++++++++ src/fingerprint.cpp | 303 ++++++ src/fingerprint.h | 107 ++ src/fm_alarm.cpp | 144 +++ src/fm_alarm_pwd.cpp | 188 ++++ src/fm_borrow_card_manager.cpp | 194 ++++ src/fm_borrow_card_user.cpp | 202 ++++ src/fm_borrow_fpr_manager.cpp | 266 +++++ src/fm_borrow_fpr_user.cpp | 270 +++++ src/fm_borrow_photo_user.cpp | 210 ++++ src/fm_borrow_pwd_manager.cpp | 183 ++++ src/fm_borrow_pwd_user.cpp | 192 ++++ src/fm_borrow_unlock.cpp | 258 +++++ src/fm_box_manage.cpp | 159 +++ src/fm_chpwd.cpp | 230 +++++ src/fm_download.cpp | 240 +++++ src/fm_info_choice.cpp | 121 +++ src/fm_info_register.cpp | 162 +++ src/fm_info_stat.cpp | 157 +++ src/fm_level.cpp | 145 +++ src/fm_log_alarm.cpp | 343 +++++++ src/fm_log_borrow.cpp | 382 +++++++ src/fm_log_main.cpp | 157 +++ src/fm_log_manager.cpp | 356 +++++++ src/fm_log_return.cpp | 382 +++++++ src/fm_log_system.cpp | 356 +++++++ src/fm_main.cpp | 211 ++++ src/fm_menu.cpp | 153 +++ src/fm_menu_pwd.cpp | 184 ++++ src/fm_mon_setting.cpp | 240 +++++ src/fm_reg_box.cpp | 275 +++++ src/fm_reg_bullet.cpp | 191 ++++ src/fm_reg_fpr1_1.cpp | 195 ++++ src/fm_reg_fpr1_2.cpp | 192 ++++ src/fm_reg_fpr1_3.cpp | 199 ++++ src/fm_reg_gun.cpp | 384 +++++++ src/fm_reg_person.cpp | 431 ++++++++ src/fm_reg_photo.cpp | 158 +++ src/fm_reg_pwd.cpp | 191 ++++ src/fm_reg_unit.cpp | 237 +++++ src/fm_return_card_manager.cpp | 188 ++++ src/fm_return_card_user.cpp | 191 ++++ src/fm_return_fpr_manager.cpp | 258 +++++ src/fm_return_fpr_user.cpp | 263 +++++ src/fm_return_photo_user.cpp | 192 ++++ src/fm_return_pwd_manager.cpp | 183 ++++ src/fm_return_pwd_user.cpp | 185 ++++ src/fm_return_unlock.cpp | 280 +++++ src/fm_safecheck.cpp | 316 ++++++ src/fm_stat_box.cpp | 191 ++++ src/fm_stat_bullet.cpp | 168 +++ src/fm_stat_gun.cpp | 374 +++++++ src/fm_stat_person.cpp | 380 +++++++ src/fm_stat_unit.cpp | 176 ++++ src/fm_system.cpp | 157 +++ src/fm_timing.cpp | 327 ++++++ src/fm_unlock.cpp | 149 +++ src/fm_unlock_pwd.cpp | 188 ++++ src/fm_user_level.cpp | 485 +++++++++ src/global_def.h | 740 ++++++++++++++ src/global_func.h | 447 ++++++++ src/global_macro.h | 245 +++++ src/lock.h | 26 + src/main.cpp | 93 ++ src/monitor.cpp | 724 +++++++++++++ src/net.cpp | 800 +++++++++++++++ src/pinyin.cpp | 1079 ++++++++++++++++++++ src/raw_i2c.cpp | 215 ++++ src/sgi_base.cpp | 1052 +++++++++++++++++++ src/sgi_base_box.cpp | 224 ++++ src/sgi_base_button.cpp | 175 ++++ src/sgi_base_check.cpp | 129 +++ src/sgi_base_edit.cpp | 213 ++++ src/sgi_base_form.cpp | 407 ++++++++ src/sgi_base_grid.cpp | 267 +++++ src/sgi_base_ime.cpp | 452 +++++++++ src/sgi_base_indicator.cpp | 65 ++ src/sgi_base_label.cpp | 95 ++ src/sgi_base_msgbox.cpp | 231 +++++ src/sgi_base_picture.cpp | 82 ++ src/sgi_base_radio.cpp | 146 +++ src/sgi_base_updown.cpp | 229 +++++ src/sgi_base_window.cpp | 104 ++ src/sgi_data.cpp | 1243 +++++++++++++++++++++++ src/sgi_data.h | 113 +++ src/sgi_form_manage.cpp | 166 +++ src/sgi_ime.cpp | 156 +++ src/sgi_log.cpp | 662 ++++++++++++ src/sgi_log.h | 74 ++ src/sgi_msgbox.cpp | 31 + src/sgi_resource.cpp | 374 +++++++ src/sgi_resource.h | 49 + src/sgi_string.c | 190 ++++ src/sgi_string.h | 34 + src/sgi_types.h | 40 + src/uart.cpp | 144 +++ src/udisk.cpp | 163 +++ temp/sgi_data.cpp | 745 ++++++++++++++ temp/sgi_data.h | 87 ++ templet/fm_xxx.cpp | 122 +++ templet/grid-temp.c | 108 ++ templet/sgi_form_xxx.cpp | 121 +++ 200 files changed, 27799 insertions(+) create mode 100644 Makefile create mode 100644 bak/sgi_data.cpp create mode 100644 bak/sgi_data.h create mode 100755 cabinet/cabinet create mode 100644 drivers/mfcard/.tmp_versions/mfcard.mod create mode 100644 drivers/mfcard/Makefile create mode 100644 drivers/mfcard/mfcard.c create mode 100644 drivers/mfcard/mfcard.h create mode 100644 drivers/mfcard/mfcard.ko create mode 100644 obj/crc.o create mode 100644 obj/finger_intf.o create mode 100644 obj/fingerprint.o create mode 100644 obj/fm_alarm.o create mode 100644 obj/fm_alarm_pwd.o create mode 100644 obj/fm_borrow_card_manager.o create mode 100644 obj/fm_borrow_card_user.o create mode 100644 obj/fm_borrow_fpr_manager.o create mode 100644 obj/fm_borrow_fpr_user.o create mode 100644 obj/fm_borrow_photo_user.o create mode 100644 obj/fm_borrow_pwd_manager.o create mode 100644 obj/fm_borrow_pwd_user.o create mode 100644 obj/fm_borrow_unlock.o create mode 100644 obj/fm_box_manage.o create mode 100644 obj/fm_chpwd.o create mode 100644 obj/fm_download.o create mode 100644 obj/fm_info_choice.o create mode 100644 obj/fm_info_register.o create mode 100644 obj/fm_info_stat.o create mode 100644 obj/fm_level.o create mode 100644 obj/fm_log_alarm.o create mode 100644 obj/fm_log_borrow.o create mode 100644 obj/fm_log_main.o create mode 100644 obj/fm_log_manager.o create mode 100644 obj/fm_log_return.o create mode 100644 obj/fm_log_system.o create mode 100644 obj/fm_main.o create mode 100644 obj/fm_menu.o create mode 100644 obj/fm_menu_pwd.o create mode 100644 obj/fm_mon_setting.o create mode 100644 obj/fm_reg_box.o create mode 100644 obj/fm_reg_bullet.o create mode 100644 obj/fm_reg_fpr1_1.o create mode 100644 obj/fm_reg_fpr1_2.o create mode 100644 obj/fm_reg_fpr1_3.o create mode 100644 obj/fm_reg_gun.o create mode 100644 obj/fm_reg_person.o create mode 100644 obj/fm_reg_photo.o create mode 100644 obj/fm_reg_pwd.o create mode 100644 obj/fm_reg_unit.o create mode 100644 obj/fm_return_card_manager.o create mode 100644 obj/fm_return_card_user.o create mode 100644 obj/fm_return_fpr_manager.o create mode 100644 obj/fm_return_fpr_user.o create mode 100644 obj/fm_return_photo_user.o create mode 100644 obj/fm_return_pwd_manager.o create mode 100644 obj/fm_return_pwd_user.o create mode 100644 obj/fm_return_unlock.o create mode 100644 obj/fm_safecheck.o create mode 100644 obj/fm_stat_box.o create mode 100644 obj/fm_stat_bullet.o create mode 100644 obj/fm_stat_gun.o create mode 100644 obj/fm_stat_person.o create mode 100644 obj/fm_stat_unit.o create mode 100644 obj/fm_system.o create mode 100644 obj/fm_timing.o create mode 100644 obj/fm_unlock.o create mode 100644 obj/fm_unlock_pwd.o create mode 100644 obj/fm_user_level.o create mode 100644 obj/main.o create mode 100644 obj/monitor.o create mode 100644 obj/net.o create mode 100644 obj/pinyin.o create mode 100644 obj/raw_i2c.o create mode 100644 obj/sgi_base.o create mode 100644 obj/sgi_base_box.o create mode 100644 obj/sgi_base_button.o create mode 100644 obj/sgi_base_check.o create mode 100644 obj/sgi_base_edit.o create mode 100644 obj/sgi_base_form.o create mode 100644 obj/sgi_base_grid.o create mode 100644 obj/sgi_base_ime.o create mode 100644 obj/sgi_base_indicator.o create mode 100644 obj/sgi_base_label.o create mode 100644 obj/sgi_base_msgbox.o create mode 100644 obj/sgi_base_picture.o create mode 100644 obj/sgi_base_radio.o create mode 100644 obj/sgi_base_updown.o create mode 100644 obj/sgi_base_window.o create mode 100644 obj/sgi_data.o create mode 100644 obj/sgi_form_manage.o create mode 100644 obj/sgi_ime.o create mode 100644 obj/sgi_log.o create mode 100644 obj/sgi_msgbox.o create mode 100644 obj/sgi_resource.o create mode 100644 obj/sgi_string.o create mode 100644 obj/uart.o create mode 100644 obj/udisk.o create mode 100644 src/crc.cpp create mode 100644 src/finger_intf.cpp create mode 100755 src/fingerprint.cpp create mode 100755 src/fingerprint.h create mode 100644 src/fm_alarm.cpp create mode 100644 src/fm_alarm_pwd.cpp create mode 100644 src/fm_borrow_card_manager.cpp create mode 100644 src/fm_borrow_card_user.cpp create mode 100644 src/fm_borrow_fpr_manager.cpp create mode 100644 src/fm_borrow_fpr_user.cpp create mode 100644 src/fm_borrow_photo_user.cpp create mode 100644 src/fm_borrow_pwd_manager.cpp create mode 100644 src/fm_borrow_pwd_user.cpp create mode 100644 src/fm_borrow_unlock.cpp create mode 100644 src/fm_box_manage.cpp create mode 100644 src/fm_chpwd.cpp create mode 100644 src/fm_download.cpp create mode 100644 src/fm_info_choice.cpp create mode 100644 src/fm_info_register.cpp create mode 100644 src/fm_info_stat.cpp create mode 100644 src/fm_level.cpp create mode 100644 src/fm_log_alarm.cpp create mode 100644 src/fm_log_borrow.cpp create mode 100644 src/fm_log_main.cpp create mode 100644 src/fm_log_manager.cpp create mode 100644 src/fm_log_return.cpp create mode 100644 src/fm_log_system.cpp create mode 100644 src/fm_main.cpp create mode 100644 src/fm_menu.cpp create mode 100644 src/fm_menu_pwd.cpp create mode 100644 src/fm_mon_setting.cpp create mode 100644 src/fm_reg_box.cpp create mode 100644 src/fm_reg_bullet.cpp create mode 100644 src/fm_reg_fpr1_1.cpp create mode 100644 src/fm_reg_fpr1_2.cpp create mode 100644 src/fm_reg_fpr1_3.cpp create mode 100644 src/fm_reg_gun.cpp create mode 100644 src/fm_reg_person.cpp create mode 100644 src/fm_reg_photo.cpp create mode 100644 src/fm_reg_pwd.cpp create mode 100644 src/fm_reg_unit.cpp create mode 100644 src/fm_return_card_manager.cpp create mode 100644 src/fm_return_card_user.cpp create mode 100644 src/fm_return_fpr_manager.cpp create mode 100644 src/fm_return_fpr_user.cpp create mode 100644 src/fm_return_photo_user.cpp create mode 100644 src/fm_return_pwd_manager.cpp create mode 100644 src/fm_return_pwd_user.cpp create mode 100644 src/fm_return_unlock.cpp create mode 100644 src/fm_safecheck.cpp create mode 100644 src/fm_stat_box.cpp create mode 100644 src/fm_stat_bullet.cpp create mode 100644 src/fm_stat_gun.cpp create mode 100644 src/fm_stat_person.cpp create mode 100644 src/fm_stat_unit.cpp create mode 100644 src/fm_system.cpp create mode 100644 src/fm_timing.cpp create mode 100644 src/fm_unlock.cpp create mode 100644 src/fm_unlock_pwd.cpp create mode 100644 src/fm_user_level.cpp create mode 100644 src/global_def.h create mode 100644 src/global_func.h create mode 100644 src/global_macro.h create mode 100644 src/lock.h create mode 100644 src/main.cpp create mode 100644 src/monitor.cpp create mode 100644 src/net.cpp create mode 100755 src/pinyin.cpp create mode 100644 src/raw_i2c.cpp create mode 100755 src/sgi_base.cpp create mode 100644 src/sgi_base_box.cpp create mode 100644 src/sgi_base_button.cpp create mode 100644 src/sgi_base_check.cpp create mode 100644 src/sgi_base_edit.cpp create mode 100644 src/sgi_base_form.cpp create mode 100644 src/sgi_base_grid.cpp create mode 100644 src/sgi_base_ime.cpp create mode 100644 src/sgi_base_indicator.cpp create mode 100644 src/sgi_base_label.cpp create mode 100644 src/sgi_base_msgbox.cpp create mode 100644 src/sgi_base_picture.cpp create mode 100644 src/sgi_base_radio.cpp create mode 100644 src/sgi_base_updown.cpp create mode 100644 src/sgi_base_window.cpp create mode 100644 src/sgi_data.cpp create mode 100644 src/sgi_data.h create mode 100644 src/sgi_form_manage.cpp create mode 100644 src/sgi_ime.cpp create mode 100644 src/sgi_log.cpp create mode 100644 src/sgi_log.h create mode 100644 src/sgi_msgbox.cpp create mode 100755 src/sgi_resource.cpp create mode 100755 src/sgi_resource.h create mode 100644 src/sgi_string.c create mode 100644 src/sgi_string.h create mode 100644 src/sgi_types.h create mode 100644 src/uart.cpp create mode 100644 src/udisk.cpp create mode 100644 temp/sgi_data.cpp create mode 100644 temp/sgi_data.h create mode 100644 templet/fm_xxx.cpp create mode 100644 templet/grid-temp.c create mode 100644 templet/sgi_form_xxx.cpp diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..47d3fcf --- /dev/null +++ b/Makefile @@ -0,0 +1,52 @@ +#Makefile for emulator +TARGET = cabinet + +SRCS_DIR = src +OBJS_DIR = obj +HPP_SRCS = $(wildcard $(SRCS_DIR)/*.h) +CC_SRCS = $(wildcard $(SRCS_DIR)/*.c) +ASM_SRCS = $(wildcard $(SRCS_DIR)/*.S) +CXX_SRCS = $(wildcard $(SRCS_DIR)/*.cpp) +CC_OBJS = $(CC_SRCS:$(SRCS_DIR)/%.c=$(OBJS_DIR)/%.o) +ASM_OBJS = $(ASM_SRCS:$(SRCS_DIR)/%.S=$(OBJS_DIR)/%.o) +CXX_OBJS = $(CXX_SRCS:$(SRCS_DIR)/%.cpp=$(OBJS_DIR)/%.o) +OBJS = $(CC_OBJS) $(ASM_OBJS) $(CXX_OBJS) + +CROSS = arm-linux- +CC = $(CROSS)gcc +CXX = $(CROSS)g++ +CC_FLAGS = -pipe -Wall -W -Wno-write-strings -O2 +CXX_FLAGS = -pipe -Wall -W -Wno-write-strings -O2 +INCS = -I. -I./src -I/opt/crosstool/arm-linux-sdl/include/SDL +LIBS = -L/opt/crosstool/arm-linux-sdl/lib -Wl,-rpath,/opt/crosstool/arm-linux-sdl/lib -lSDL -lSDL_image -lSDL_ttf -lSDL_mixer -lpthread -lm -lz + +#all : check_dir $(TARGET) + +$(TARGET): $(OBJS) $(HPP_SRCS) + $(CXX) -o $@ $^ $(INCS) $(LIBS) + arm-linux-strip $(TARGET) + + +$(CC_OBJS): $(OBJS_DIR)/%.o : $(SRCS_DIR)/%.c + $(CC) $(CC_FLAGS) $(INCS) -o $@ -c $< + +$(ASM_OBJS): $(OBJS_DIR)/%.o : $(SRCS_DIR)/%.S + $(CC) $(CC_FLAGS) $(INCS) -o $@ -c $< + +$(CXX_OBJS): $(OBJS_DIR)/%.o : $(SRCS_DIR)/%.cpp + $(CXX) $(CXX_FLAGS) $(INCS) -o $@ -c $< + +.PHONY : check_dir +check_dir: + @echo $(OBJS_DIR) + test -d $(OBJS_DIR) || mkdir -p $(OBJS_DIR) + +.PHONY : install +install: + rm -f /home/franki/minicom/upload/$(TARGET) + cp $(TARGET) /home/franki/minicom/upload/. + +.PHONY : clean +clean: + rm -f $(TARGET) + rm -rf $(OBJS_DIR)/* diff --git a/bak/sgi_data.cpp b/bak/sgi_data.cpp new file mode 100644 index 0000000..1569c68 --- /dev/null +++ b/bak/sgi_data.cpp @@ -0,0 +1,237 @@ +#include "global_func.h" + +static std::vector s_person_vec; + +s32 data_open(void) +{ + u32 i; + u32 count; + struct person_data person; + + /* 清空人员记录数据 */ + s_person_vec.clear(); + + /* 打开人员数据文件 */ + FILE *fp = fopen(DATA_FILE(person), "rb"); + if (fp == NULL) { + return FAIL; + } + + /* 获取记录数 */ + fseek(fp, 0, SEEK_END); + count = ftell(fp) / sizeof(struct person_data); + fseek(fp, 0, SEEK_SET); + + /* 读取人员数据 */ + for (i = 0; i < count; ++i) { + fread(&person, 1, sizeof(struct person_data), fp); + s_person_vec.push_back(person); + } + + /* 关闭数据文件 */ + fclose(fp); + + return 0; +} + +s32 search_uid(struct sgi_passport *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].level == LV_USER + && (s_person_vec[i].fpr1 == param || + s_person_vec[i].fpr2 == param)) { + sgi_ncp16(pass->uid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->name, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].level == LV_USER + && s_person_vec[i].idcard == param) { + sgi_ncp16(pass->uid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->name, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 search_mid(struct sgi_passport *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].level == LV_MANAGER + && (s_person_vec[i].fpr1 == param || + s_person_vec[i].fpr2 == param)) { + sgi_ncp16(pass->mid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->mname, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].level == LV_MANAGER + && s_person_vec[i].idcard == param) { + sgi_ncp16(pass->mid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->mname, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 verify_user_pwd(struct sgi_passport *pass, u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].level != LV_USER + || (sgi_ncmp16(s_person_vec[i].uid, uid, + COUNTOF(s_person_vec[i].uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].pwd, pwd, + COUNTOF(s_person_vec[i].pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->uid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->name, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + } + r = i; + } + + break; + } + + return r; +} + +s32 verify_manager_pwd(struct sgi_passport *pass, u16 *mid, u16 *pwd) +{ + assert(mid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].level != LV_MANAGER + || (sgi_ncmp16(s_person_vec[i].uid, mid, + COUNTOF(s_person_vec[i].uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].pwd, pwd, + COUNTOF(s_person_vec[i].pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->mid, s_person_vec[i].uid, + COUNTOF(s_person_vec[i].uid)); + sgi_ncp16(pass->mname, s_person_vec[i].name, + COUNTOF(s_person_vec[i].name)); + } + r = i; + } + + break; + } + + return r; +} + +static s32 verify_all_user_pwd(u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_person_vec[i].uid, uid, + COUNTOF(s_person_vec[i].uid)) != 0) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].pwd, pwd, + COUNTOF(s_person_vec[i].pwd)) == 0) { + r = i; + } + + break; + } + + return r; +} + +s32 change_pwd(u16 *uid, u16 *old_pwd, u16 *new_pwd) +{ + assert(uid != NULL || old_pwd != NULL || new_pwd != NULL); + + s32 r; + + /* 校验旧密码是否有效 */ + r = verify_all_user_pwd(uid, old_pwd); + if (r < 0) { + return r; + } + + /* 修改为新密码 */ + sgi_ncp16(s_person_vec[r].pwd, new_pwd, COUNTOF(s_person_vec[r].pwd)); + + return 0; +} + +void data_close(void) +{ + s_person_vec.clear(); +} diff --git a/bak/sgi_data.h b/bak/sgi_data.h new file mode 100644 index 0000000..436f26b --- /dev/null +++ b/bak/sgi_data.h @@ -0,0 +1,51 @@ +#ifndef SGI_DATA_H +#define SGI_DATA_H + +#include "sgi_types.h" + +struct person_data { + u16 uid[16]; + u16 name[16]; + u8 sex; + u8 age; + u8 dept; + u8 level; + u16 fpr1; + u16 fpr2; + u32 idcard; + u16 pwd[16]; +}; + +struct gun_data { + u16 code[16]; + u16 model[16]; + u16 caliber[8]; + u16 bullet[8]; + u16 holder[16]; + u16 unit[16]; + u16 stock_date[16]; + u16 lock_code; + u16 status; +}; + +struct box_data { + u16 type; + u16 cap; + u16 code[16]; + u16 model[16]; + u16 manager[16]; + u16 unit[16]; +}; + +struct sgi_passport { + u32 visit; + u16 uid[16]; + u16 name[16]; + u16 dept[16]; + u16 mid[16]; + u16 mname[16]; + u16 mdept[16]; + char photo[64]; +}; + +#endif diff --git a/cabinet/cabinet b/cabinet/cabinet new file mode 100755 index 0000000000000000000000000000000000000000..f6e14923b5e3e6d1d69ed0f1dfba99ee0ce5ef8e GIT binary patch literal 278476 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�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�X;J^#Ild+%pY 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 literal 0 HcmV?d00001 diff --git a/drivers/mfcard/.tmp_versions/mfcard.mod b/drivers/mfcard/.tmp_versions/mfcard.mod new file mode 100644 index 0000000..a487164 --- /dev/null +++ b/drivers/mfcard/.tmp_versions/mfcard.mod @@ -0,0 +1,2 @@ +/home/franki/projects/franki/drivers/mfcard/mfcard.ko +/home/franki/projects/franki/drivers/mfcard/mfcard.o diff --git a/drivers/mfcard/Makefile b/drivers/mfcard/Makefile new file mode 100644 index 0000000..abc93d1 --- /dev/null +++ b/drivers/mfcard/Makefile @@ -0,0 +1,14 @@ +obj-m:=mfcard.o +KDIR:=/opt/crosstool/source/linux-3.0.8 +PWD:=$(shell pwd) +all: + $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules + @rm -rf *.mod.* + @rm -rf .*.cmd + @rm -rf *.o + @rm -rf modules.* + @rm -rf Module.* + +clean: + rm -rf *.ko + diff --git a/drivers/mfcard/mfcard.c b/drivers/mfcard/mfcard.c new file mode 100644 index 0000000..c415ad7 --- /dev/null +++ b/drivers/mfcard/mfcard.c @@ -0,0 +1,466 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +//#include +#include + +//#include +//#include +#include + +#include "mfcard.h" + +#if 0 +#define GPG2CON (mfcard_devp->gpio + S5P_GPG2CON) +#define GPG2DAT (mfcard_devp->gpio + S5P_GPG2DAT) +#define GPG2PUD (mfcard_devp->gpio + S5P_GPG2PUD) +#define GPH1CON (mfcard_devp->gpio + S5P_GPH1CON) +#define GPH1DAT (mfcard_devp->gpio + S5P_GPH1DAT) +#define GPH1PUD (mfcard_devp->gpio + S5P_GPH1PUD) + +#define WD0() ((__raw_readl(GPH1DAT) & (1 << 3)) == 0) +#define WD1() ((__raw_readl(GPG1DAT) & (1 << 1)) == 0) +#endif + +struct mfcard_dev_t *mfcard_devp = NULL; +static int s_mfcard_major = MFCARD_MAJOR; + +struct mfcard_gpio_desc mfcard[] = { + {S5PV210_GPH2(0), 0, "WD0"}, + {S5PV210_GPH2(1), 1, "WD1"}, +}; + +static atomic_t s_card_id = {0}; +static atomic_t s_card_read_state = {0}; +static volatile int s_card_bit = 0; +static volatile int s_card_bit_count = 0; + +static int data_check(void) +{ + int d = atomic_read(&s_card_id); + int nums1 = 0; + int nums2 = 0; + int i; + + int b0 = (d >> 25) & 1; /* 前12bit偶校验 */ + int b25 = d & 1; /* 后12bit奇校验 */ + + for (i = 0; i < 12; ++i) { + nums1 += (d >> (25 - 1 - i)) & 1; + nums2 += (d >> (12 - i)) & 1; + } + + printk(KERN_INFO "b0: %x, b1: %x\n", nums1, nums2); + if (b0 == (nums1 & 1) && b25 == (~nums2 & 1)) { + d = (d >> 1) & 0x00ffffff; + atomic_set(&s_card_id, d); + return 1; + } + + return 0; +} + +static void mfcard_timer(unsigned long data) +{ + atomic_set(&s_card_id, s_card_bit); + if (data_check()) { + atomic_set(&s_card_read_state, 1); + } + else { + atomic_set(&s_card_read_state, -1); + } + printk(KERN_INFO "card id: %08X\n", atomic_read(&s_card_id)); + s_card_bit = 0; + s_card_bit_count = 0; +} + +static irqreturn_t mfcard_interrupt(int irq, void *dev_id) +{ + struct mfcard_gpio_desc *bdata = (struct mfcard_gpio_desc *)dev_id; + + //printk(KERN_INFO "v: %d\n", bdata->val); + s_card_bit_count++; + + if (s_card_bit_count < 26) { + s_card_bit <<= 1; + s_card_bit |= bdata->val; + } + else if (s_card_bit_count == 26) { + s_card_bit <<= 1; + s_card_bit |= bdata->val; + mod_timer(&bdata->timer, jiffies + msecs_to_jiffies(1)); + } + + return IRQ_HANDLED; +} + +static void s5p_mfcard_port_open(void) +{ + unsigned int reg_val; + int irq; + int i; + int err = 0; + +#if 0 + if (mfcard_devp == NULL) { + return; + } +#endif + + /* 配置声光报警控制引脚 */ + err = gpio_request(BJ_SPK, "BJ-SPK"); + if (err) { + printk(KERN_INFO "request BJ_SPK fail.\n"); + } + gpio_set_value(BJ_SPK, 0); + s3c_gpio_cfgpin(BJ_SPK, S3C_GPIO_OUTPUT); + + /* 配置指纹电源控制引脚 */ + err = gpio_request(PW_CTRL, "PW_CTRL"); + if (err) { + printk(KERN_INFO "request PW_CTRL fail.\n"); + } + gpio_set_value(PW_CTRL, 1); + s3c_gpio_cfgpin(PW_CTRL, S3C_GPIO_OUTPUT); + + /* 配置大门锁控制引脚 */ + err = gpio_request(DOOR_CTRL, "DOOR_CTRL"); + if (err) { + printk(KERN_INFO "request DOOR_CTRL fail.\n"); + } + gpio_set_value(DOOR_CTRL, 1); + s3c_gpio_cfgpin(DOOR_CTRL, S3C_GPIO_OUTPUT); + + /* 配置大门锁反馈引脚 */ + err = gpio_request(DOOR_FB, "DOOR_FB"); + if (err) { + printk(KERN_INFO "request DOOR_FB fail.\n"); + } + s3c_gpio_cfgpin(DOOR_FB, S3C_GPIO_INPUT); + + /* 指纹按下检测 */ + err = gpio_request(FPR_DETECT, "FPR_DETECT"); + if (err) { + printk(KERN_INFO "request FPR_DETECT fail.\n"); + } + s3c_gpio_cfgpin(FPR_DETECT, S3C_GPIO_INPUT); + + /* 供电检测 */ + err = gpio_request(PW_JC, "PW_JC"); + if (err) { + printk(KERN_INFO "request PW_JC fail.\n"); + } + s3c_gpio_cfgpin(PW_JC, S3C_GPIO_INPUT); + + /* 在位检测1 */ + err = gpio_request(QWZ1, "QWZ1"); + if (err) { + printk(KERN_INFO "request QWZ1 fail.\n"); + } + s3c_gpio_cfgpin(QWZ1, S3C_GPIO_INPUT); + + /* 在位检测2 */ + err = gpio_request(QWZ2, "QWZ2"); + if (err) { + printk(KERN_INFO "request QWZ2 fail.\n"); + } + s3c_gpio_cfgpin(QWZ2, S3C_GPIO_INPUT); + + /* 获取GPIO访问指针 */ + //mfcard_devp->gpio = ioremap(GPIO_BASE, GPIO_SIZE); + + for (i = 0; i < ARRAY_SIZE(mfcard); i++) { + setup_timer(&mfcard[i].timer, mfcard_timer, + (unsigned long)&mfcard[i]); + + irq = gpio_to_irq(mfcard[i].gpio); + printk(KERN_INFO "%s: %d\n", mfcard[i].name, irq); + err = request_irq(irq, mfcard_interrupt, IRQ_TYPE_EDGE_FALLING, + mfcard[i].name, (void *)&mfcard[i]); + + if (err) { + break; + } + } + + if (err) { + for (; i > 0; i--) { + irq = gpio_to_irq(mfcard[i - 1].gpio); + disable_irq(irq); + free_irq(irq, (void *)&mfcard[i - 1]); + + del_timer_sync(&mfcard[i - 1].timer); + } + printk(KERN_INFO "request fail: %x.\n", err); + } + +#if 0 + /* 配置MFCARD通讯端口 */ + /* GPG1_1 = input */ + reg_val = __raw_readl(GPG2CON); + reg_val &= ~(0xf << 4); + __raw_writel(reg_val, GPG2CON); + + /* GPH1_3 = input */ + reg_val = __raw_readl(GPH1CON); + reg_val &= ~(0xf << 12); + reg_val |= 1 << 12; + __raw_writel(reg_val, GPH1CON); + + reg_val = __raw_readl(GPH1DAT); + reg_val |= 1 << 3; + __raw_writel(reg_val, GPH1DAT); + + printk(KERN_INFO "GPH1CON: 0x%x.\n", __raw_readl(GPH1CON)); + printk(KERN_INFO "GPG2CON: 0x%x.\n", __raw_readl(GPG2CON)); +#endif +} + +static void s5p_mfcard_port_close(void) +{ + //iounmap(mfcard_devp->gpio); +} + +int mfcard_open(struct inode *inodep, struct file *filep) +{ + printk(KERN_INFO "mfcard open()\n"); + filep->private_data = mfcard_devp; + + return 0; +} + +int mfcard_release(struct inode *inodep, struct file *filep) +{ + printk(KERN_INFO "mfcard release()\n"); + + return 0; +} + +static long mfcard_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) +{ + long val; + + switch (cmd) { + case MFCARD_IOCTL_ALARM: + if (get_user(val, (long *)arg)) { + return -EFAULT; + } + + gpio_set_value(BJ_SPK, val & 1); + break; + + case MFCARD_IOCTL_PW_CTRL: + if (get_user(val, (long *)arg)) { + return -EFAULT; + } + + gpio_set_value(PW_CTRL, val & 1); + break; + + case MFCARD_IOCTL_CARD_START: + atomic_set(&s_card_id, 0); + atomic_set(&s_card_read_state, 0); + break; + + case MFCARD_IOCTL_CARD_STATE: + val = atomic_read(&s_card_read_state); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + + case MFCARD_IOCTL_CARD_READ: + val = atomic_read(&s_card_id); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + case MFCARD_IOCTL_FPR_STATE: + val = gpio_get_value(FPR_DETECT); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + case MFCARD_IOCTL_DOOR_CTRL: + if (get_user(val, (long *)arg)) { + return -EFAULT; + } + + gpio_set_value(DOOR_CTRL, val & 1); + break; + + case MFCARD_IOCTL_DOOR_FB: + val = gpio_get_value(DOOR_FB); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + case MFCARD_IOCTL_PW_JC: + val = gpio_get_value(PW_JC); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + case MFCARD_IOCTL_QWZ1: + val = gpio_get_value(QWZ1); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + case MFCARD_IOCTL_QWZ2: + val = gpio_get_value(QWZ2); + if (put_user(val, (long *)arg)) { + return -EFAULT; + } + break; + + default: + return -EINVAL; + } + + return 0; +} + +static ssize_t mfcard_read(struct file *filep, char __user *buf, size_t size, + loff_t *ppos) +{ + printk(KERN_INFO "mfcard read()\n"); + + return 0; +} + +static ssize_t mfcard_write(struct file *filep, const char __user *buf, + size_t size, loff_t *ppos) +{ + printk(KERN_INFO "mfcard write()\n"); + + return 0; +} + +static const struct file_operations mfcard_fops = +{ + .owner = THIS_MODULE, + .read = mfcard_read, + .write = mfcard_write, + .unlocked_ioctl = mfcard_ioctl, + .open = mfcard_open, + .release = mfcard_release, +}; + +static struct miscdevice misc_mfcard_dev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "mfcard", + .fops = &mfcard_fops, +}; + +static void mfcard_setup_cdev(struct mfcard_dev_t *devp, int index) +{ + int err; + dev_t devno = MKDEV(s_mfcard_major, index); + + cdev_init(&devp->cdev, &mfcard_fops); + devp->cdev.owner = THIS_MODULE; + err = cdev_add(&devp->cdev, devno, 1); + if (err) { + printk(KERN_NOTICE "Error %d adding mfcard %d\n", err, index); + } +} + +int __init mfcard_init(void) +{ + int result; + dev_t devno = MKDEV(s_mfcard_major, 0); + + printk(KERN_INFO "mfcard init()\n"); + +#if 0 + /* 申请设备号 */ + if (s_mfcard_major) { + /* 静态申请设备号 */ + result = register_chrdev_region(devno, 1, "mfcard"); + } + else { + /* 动态申请设备号 */ + result = alloc_chrdev_region(&devno, 0, 1, "mfcard"); + s_mfcard_major = MAJOR(devno); + } + + if (result < 0) { + return result; + } + + /* 动态申请设备结构体内存 */ + mfcard_devp = kmalloc(sizeof(struct mfcard_dev_t), GFP_KERNEL); + if (mfcard_devp == NULL) { + result = -ENOMEM; + goto fail_kmalloc; + } + + memset(mfcard_devp, 0, sizeof(struct mfcard_dev_t)); + mfcard_setup_cdev(mfcard_devp, 1); +#endif + + /* 配置通讯端口 */ + printk(KERN_INFO "config mfcard gpio.\n"); + s5p_mfcard_port_open(); + + result = misc_register(&misc_mfcard_dev); + + return result; + +//fail_kmalloc: +// unregister_chrdev_region(devno, 1); +// return result; +} + +void __exit mfcard_exit(void) +{ + int irq; + int i; + + printk(KERN_INFO "mfcard exit.\n"); + + for (i = 0; i < ARRAY_SIZE(mfcard); ++i) { + irq = gpio_to_irq(mfcard[i].gpio); + free_irq(irq, (void *)&mfcard[i]); + + del_timer_sync(&mfcard[i].timer); + } + +#if 0 + cdev_del(&mfcard_devp->cdev); + kfree(mfcard_devp); + unregister_chrdev_region(MKDEV(s_mfcard_major, 0), 1); +#endif + + /* 释放已影射的通讯IO端口 */ + s5p_mfcard_port_close(); + + misc_deregister(&misc_mfcard_dev); +} + +module_param(s_mfcard_major, int, S_IRUGO); +module_init(mfcard_init); +module_exit(mfcard_exit); + +MODULE_AUTHOR("franki"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("Mifeare card driver"); diff --git a/drivers/mfcard/mfcard.h b/drivers/mfcard/mfcard.h new file mode 100644 index 0000000..04fbfef --- /dev/null +++ b/drivers/mfcard/mfcard.h @@ -0,0 +1,65 @@ +#ifndef MFCARD_H +#define MFCARD_H + +#include +#include +#include +#include + +#define MFCARD_MAGIC 'E' +#define MFCARD_MAJOR 250 +#define MFCARD_IOCTL_ALARM _IOW(MFCARD_MAGIC, 1, int) +#define MFCARD_IOCTL_PW_CTRL _IOW(MFCARD_MAGIC, 2, int) +#define MFCARD_IOCTL_DOOR_CTRL _IOW(MFCARD_MAGIC, 3, int) +#define MFCARD_IOCTL_CARD_START _IOW(MFCARD_MAGIC, 4, int) +#define MFCARD_IOCTL_CARD_STATE _IOR(MFCARD_MAGIC, 5, int) +#define MFCARD_IOCTL_CARD_READ _IOR(MFCARD_MAGIC, 6, int) +#define MFCARD_IOCTL_FPR_STATE _IOR(MFCARD_MAGIC, 7, int) +#define MFCARD_IOCTL_DOOR_FB _IOR(MFCARD_MAGIC, 8, int) +#define MFCARD_IOCTL_PW_JC _IOR(MFCARD_MAGIC, 9, int) +#define MFCARD_IOCTL_QWZ1 _IOR(MFCARD_MAGIC, 10, int) +#define MFCARD_IOCTL_QWZ2 _IOR(MFCARD_MAGIC, 11, int) + +#define GPIO_BASE 0xE0200000 +#define GPIO_SIZE 0x1000 /* Page size */ + +#define S5P_GPG2CON 0x01E0 +#define S5P_GPG2DAT 0x01E4 +#define S5P_GPG2PUD 0x01E8 +#define S5P_GPG2DRV 0x01EC + +#define S5P_GPH1CON 0x0C20 +#define S5P_GPH1DAT 0x0C24 +#define S5P_GPH1PUD 0x0C28 +#define S5P_GPH1DRV 0x0C2C + +#if 0 +#define PW_CTRL S5PV210_GPH1(3) +#define DOOR_FB S5PV210_GPG2(3) +#define DOOR_CTRL S5PV210_GPG2(5) +#define FPR_DETECT S5PV210_GPG2(4) +#define BJ_SPK S5PV210_GPG2(6) +#else +#define PW_CTRL S5PV210_GPG2(0) +#define DOOR_FB S5PV210_GPG2(2) +#define DOOR_CTRL S5PV210_GPG2(3) +#define FPR_DETECT S5PV210_GPG2(4) +#define BJ_SPK S5PV210_GPG2(5) +#define PW_JC S5PV210_GPH1(3) +#define QWZ1 S5PV210_GPH2(2) +#define QWZ2 S5PV210_GPH2(3) +#endif + +struct mfcard_dev_t { + struct cdev cdev; + void __iomem *gpio; +}; + +struct mfcard_gpio_desc { + int gpio; + int val; + char *name; + struct timer_list timer; +}; + +#endif /* MFCARD_H */ diff --git a/drivers/mfcard/mfcard.ko b/drivers/mfcard/mfcard.ko new file mode 100644 index 0000000000000000000000000000000000000000..4781c37f304f5554e8b3533d5d98095c023ef815 GIT binary patch literal 103128 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 @?AkpBpKEN{lO9}mA0NuLW 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 lmRX@?W{e4gj~{r!I5=X{^{dEcYk#XB$z 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%0DnEe{}kZw2KaSw?$-|VwG1ox zDLD6MyXH%A8E`*(`c>fEe;(fi&i&@`r@@)ely&-g)YLsll|3`J9gg0v^a`r$x) zBN890WIL8hrmUfCa(G;#1AV*ucYbeAOxn}RD$e)Ua?^{%xDs`jd`&1>SF(_VDc#zV z<)%!^A4MBWR?#kvWgVrDm#o3D(jiZ)Vqk(eE`>3NE|i2R;5d^Yd$iyjLX2Wr+00zN1J3iO$(heNukJr!jn5dovB&wBs@oXES1fdY>NXMm+x;Ku(sOS z* z7ojd3KLwvNhp~*lc~>5kg6kVpZ17stRzlhLcw%?C zluSiO=l(r{PS??PG@l;J+SpfW`E&-#j7*7YIjNE$j#3KKyI2a(rPPR>E+mV|(VEIl zVr%oQyFsEijI2IWGdqyUW@)5`qm9zG8x7Wy5vqk&1BsD(S}$9EE{`4bxicG=VT&!? zLE#{wJb}D~XQ~s(v)YDaVhiz`$d!n=KoXkstW&<9xZ2IP+8)Q1^ zU7CovMu=;Wq!D8x4l$1ZeQAE42>UmQNFXm0;cuR}R^%=biMENpDeob|K0$>4XNd5> zj|l(!iSR$7xkE&|7l`Xbj%$9Fi1z0-&S?2tMEsKBT}nM3TGhT)V;d2PLA&NLBI4OX z+=y`!(QbkWyD|~|AJ@oysR2I_&T2fTahixta$fV_XuP0tM(f|y{G!IUG`^!z-cX`cO8x?;+*OwcON*qp0k$l@wx074~XGmx>eRDUktkIR8K7 CMS=MM literal 0 HcmV?d00001 diff --git a/obj/fingerprint.o b/obj/fingerprint.o new file mode 100644 index 0000000000000000000000000000000000000000..05ee92f066f2a98e8a0f73519fd43c6c0b3bafa7 GIT binary patch literal 4360 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 Y(P6yASYcdZTxR?g;|k*kj8(?}0t$j5mjD0& literal 0 HcmV?d00001 diff --git a/obj/fm_alarm.o b/obj/fm_alarm.o new file mode 100644 index 0000000000000000000000000000000000000000..8f059e6d99cd8fe22091984af8acea32412b021d GIT binary patch literal 9404 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 literal 0 HcmV?d00001 diff --git a/obj/fm_alarm_pwd.o b/obj/fm_alarm_pwd.o new file mode 100644 index 0000000000000000000000000000000000000000..9379c5962ea53b09cab86311573d6135f91d1c3a GIT binary patch literal 11060 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 M)0##DAMuI&FPh0-^#A|> literal 0 HcmV?d00001 diff --git a/obj/fm_borrow_fpr_manager.o b/obj/fm_borrow_fpr_manager.o new file mode 100644 index 0000000000000000000000000000000000000000..c37c8a2530cbc8af67b56933d61baa4bacdc41c9 GIT binary patch literal 12288 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 literal 0 HcmV?d00001 diff --git a/obj/fm_borrow_pwd_manager.o b/obj/fm_borrow_pwd_manager.o new file mode 100644 index 0000000000000000000000000000000000000000..65ac49db21d384e32ba71b4548c5277d25f8b2e9 GIT binary patch literal 11012 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 WAuZs$K^KnU57Mfu4f;*L$o~MmM#1&~ literal 0 HcmV?d00001 diff --git a/obj/fm_box_manage.o b/obj/fm_box_manage.o new file mode 100644 index 0000000000000000000000000000000000000000..6f6c06e16047b2181a1b1f11a2902a0d16d45fbc GIT binary patch literal 10552 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 WupM#-@SYL;LE8RR3%{~Wi2nr{Xc1Zf literal 0 HcmV?d00001 diff --git a/obj/fm_chpwd.o b/obj/fm_chpwd.o new file mode 100644 index 0000000000000000000000000000000000000000..6e4d5e566a9b7cd1a15520557c5e9b607576405b GIT binary patch literal 12456 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 literal 0 HcmV?d00001 diff --git a/obj/fm_download.o b/obj/fm_download.o new file mode 100644 index 0000000000000000000000000000000000000000..d7983a6889a40ca60a825c3d754083df203ff154 GIT binary patch literal 12444 zcmcIqe{5XEouBot6Jt!WN!H-N;w-`COkyv)PDl)-iA|gzv`#Qdj;3jj=k@N|Ub5a@ zcGphmaXlw-auJHJQO`mV3H4UZ^?WD(@Ts(iDv+Ei6skro)uCSQE)r{Ro@#Okxl*J< z6!3jM@6GJKeRT?)#E8jfzB8Zse!ugbd9yQP{&rjEc89|uRC0($QIdq{t~FXJ*Bj6% z*2?x8$V-ryB9p%ic?GgZ%C`gSkXItt&p$8?CE#pq*S1fWAOmVWNIa z7rtEKlz&9O=3k*#xR0W4M6d82D_rwCbvNv%Xum5rJ<&d{kHtMY`!5pRc_F$AP9c6) zDRR?>PLV65z#j>X>!&uqpbN3LuttbGf4QW?vF~^0jZ1%He*XG7_^jf&3;vYH{-iDTCGJHzF4cFU{sqL^WB5g%7<0y3 zAb!{UE}cG}f?pH$Ck?-@!nPWt5eK&!2kSV0298IJ>osVj-&2r3T!j^djjO$!yr#AnCF>jdnDhK?bF6#9_FV~6N;JrR8`-``+pj)NlPPDo5&3gO0 zyJnOgtou9L-yNM1SQi{0^|fKWHu#_~kej|uuAMsAxXqoLRyN3+Gkp~Mp`Uh`=;L@|S(9hw`6LX{ZRyTx{6><{cZIg{Ur_0TplQ;GPUdmvX>1bdB}T!zoBmzEah zfAe_3)itWuFUeuPNA*fyZu+&<$aKr*Tw&tPah?6xC-*C}56j(dQ~&8Z(2jXxAJz-# zaiz>SQRY1PydK@V$)neFk7CSEO#jFssw;t_`)DoNYF(HEpVy^#d;@cixu=h6&$#dl z(?1W^)?0}63#)R4m57rgFMWj#&XW`JYxxnw9{c`y)iz`NH*Uw+125^UyB#{{kJ4TA z3qI4Y5%?v<69v(AwD!{S+M-{tJUOnP`);l`X<;zVkhR$588Ixh?-V+ps z&@y5AH)Z-qj%y0~A-_6x!tjrE{qT#v?34bnu1@;La#`FEPx{xb{7W6JZQ3x7*sUn~ z=o>16c@v*HEIu`T0iWtEKDlf@35!o^yw*6K`*qHU z)9-KM)1;>qr?V)3-Z*_C6aq?a^&A_5VC-J#71&$x zO>nPKx)m0`NxA0#&EjLL&Bw;$rjH%a%{^o3b313KXKwQeM!Q^sKsxex32h|_NPssbI?nlY47}I za}Rk6es;mn0e7zO1pS;sc8|_h0?C`4dZW01G{QH2O9y{Gt{+61?fao~Km9~(x!*9x z_IMxJy5MpLt&5`HgmW!WP$G z{t=hnhVoV5Cg3d4{r2e0+|k!(1L#}hGtUm+{B-`h&m#XdWVc1mK^7MIBIG%qvt)lP zr0aQ$?8KSnZHwFhdCDR`26@sVry=Jo@>$4dEb>LjJof~6X^@FWx%0R@@a~`z&qq90 zTyf#7w^)eDTZHg}cp4WFA4qM;0c55w

r@GSda*VdS⩔(XnF`?|=cVOcfZYy_J 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 Yi#E0cJAik88~-4!;lm!%eL*4q5BDEG1^@s6 literal 0 HcmV?d00001 diff --git a/obj/fm_info_choice.o b/obj/fm_info_choice.o new file mode 100644 index 0000000000000000000000000000000000000000..de1f0a88a657e38bdae67e52cc7db7d23ac6b28b GIT binary patch literal 9400 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 P;0JO83nABDE5v^RNo#6X literal 0 HcmV?d00001 diff --git a/obj/fm_info_register.o b/obj/fm_info_register.o new file mode 100644 index 0000000000000000000000000000000000000000..61dec2438d9b5712b2509c3c82d557e702c6d303 GIT binary patch literal 10988 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

sRaBp!8KKeeWzYkDZd2dcnryJoH}B<38>f zchWYG2HUv*s>apxxQ21NQKysEH|)@N3i>!-fMDpZ=kZTUpPomvcCb>YRqufPD3|6z z9_OJx11x>)(gofM)t4}b0k!{lFIyT{>MQNbAoOjw_0#kCTZg`R=<5WJ^WdJ<`rc6b z09G=WnMXnLO8bL6&V#y`^tkUi#{CEblE-oHRy@j!;PFmc@84t4r*)vZRQ_*=KC!8+ z&#!pYcMBBJ=b&3@av6QA6^}6-(=>QDWYPMi4b-#I!888^Uq22Wxgo_1sx}WM6|nKB zi}_*2(@pK1ye*N#^cC>%FC`_!n&55G0#Ng~55Oy>ICv3Th2{~pPe`7|8F>{4DcmT& zg3LMikXInvx{E%%0KQR;N|m%eEo-#bd&KV%y_S=^^b}>CyR>Sx>=moZbd)?|jgs+L zV7Glm&^}sOPHvpIjE&2w4qwsotkeDZe&cIF%g>?QWRt&xGM}Ap{~5}BFKPKrly}?Y z4^gJhv&gh>mE8f*ytYF23Z8fD!!gLGz3WOG^oOj!w>kgH`8elW@9-C`EGM_MqwMl+ z4t+e?%gK$?w9^0jbd?;p^;aT0zrmr8Cu}*najI47)2E!|xUDB)=dX9@lky+9p{?Y6 z{&za`-zmb%m)pUwDxF5Mw_DsL3+mU66R6U^Jdw)DE&Pslf4LDQx7g@tcgi*5S!IvB zW6{x*RO1%+I{G_huQ;swbLK9boZo@mk8%Q=nDTkZS5VgS&mnhWpKAFv$QNqMGT&1^ zyz6v(0W!~8E&m?!b(|eqc0)Jsv9!DrGVijqya6)ru(T{^CV$;n|CRpbPAez3_>u^r ze>qhM@Gqmka&n6=mj#sErPEJVyYa;B$qmNiwkn=$-41!gAwTbsPdMc7JLDfbId_o7a;zutBzQ@$56&x=NsSK++)Ge>)$l3UTf5vSM-j`nXWx!G!8 zDPD5OKUFegqm9_lx7fBI$6xJ`*F)w#;Un0yw5Q$C-tCZk9rA=j{;@-T+aZ7KkT==h zQM9keF2k2!v&(2tK&Fa=$SWC{*e|pK(Nsz_MTBvnI~2k#lQ9~Jj~U}B^+k?PI5RmW zng+`RUMYQw!0thIA4pCt*|^ziv~IMPY_~e&_G`&TtFyc+Te96UoL6g0wss^25(d6# zW5!TAG8*gI%BzM%WB}jJDSR~tf+EnpErg%0z1wy_wLfT0b@@)h*wy{i<6Yf`kr^K_ zo-l?DyFb~vGh-Z$4-Usn2=L4Ds&;gY@mk4p9{P+8THe>PHrp;olY=oW)1#cUCAVh` z%F;=!*(xjGQhU3+Q?#|?d0Fj2N$110%UlhR_m*#Q9>iUcHD%Ql+N`gMjLb;#XiteL zS=P;IbR-#%#$-i0Hq1pL1>6|mR?J!zwhG#84PiB_DOnZlY)#pWkH$nI8I2^YQs!tX z9UsFztZ^W;B@;8%O_IU85#y-siT4~8z1zEuT`{vS9zC29hGAV5Lg~>s+>gy*q|#gg z?LqrfH3nn2_DDW|Wa$ney6AIU^BD&Q6Ftyn_bcz%Dk?&<;tRb%8jX#PCXaAMjU7FN z-_X{ISx3_`Y#Z7Y3h^S)03Y79J!4rxLWj-msbr?&MlZuelKt6W@8SBWf@f0<@~7J2W`Zmq|<`vp{-mX+meZ7`ZLv* z*STQ~W|GE8WNa`2PpSn4zfE9kIt~Y%z(Ta(BZTL1E0AH|T~Er`yQN!xm$U*IWwM@e ze9IpB?rR15Recld_sZ||Rv_Pf!0oDjH|zHyW?(%K zO_rWPVB>zgJBYpVKXr6VbXpe z+na!FKL~6b5MqKDMI1-O;B&+n^b&`lkBGk+G~oS4UYH0TV;%DPi6cTV)*HLl$XA;OL@u^#hQ^}AJlH}Mwi6II`*@EL^%74{RMXOM_* zkr7p&AmZ7iR6C|?&5yCIHE-Z1tX0+%eF}LFQ1&ZqRv1*sea?2G_;c8=52+vS9$H!7VWW literal 0 HcmV?d00001 diff --git a/obj/fm_level.o b/obj/fm_level.o new file mode 100644 index 0000000000000000000000000000000000000000..b67b559811635f0810c0587703de82db947a9ba0 GIT binary patch literal 10084 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 literal 0 HcmV?d00001 diff --git a/obj/fm_log_alarm.o b/obj/fm_log_alarm.o new file mode 100644 index 0000000000000000000000000000000000000000..3edb69f3827c4d327020a0231716965882968e69 GIT binary patch literal 11856 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

sRaBtn}3=eQ&Qak6n_NdBMixJoH}B z<9^98?rGaR8g1kLn;KWo;~K{8N1aYu-`(+QCYpR=pGU zqgd7Ov(6tMKMOD}l0sJ?^+45e=GpO@1C zu<@vi`4Pp_O4m@N7Ozc`4rB`t2jvE zM)752&VlQUYtPnQ9Ks9WL@g>+()zTl(O&Nn|AFYWn%tGADC^vnRjXxhWk1UrkM(y6 zmho6%w|zy>K3Z8#Zk)LKIm+64@h}SPtNSCQw!Ve6Y(j3fwVy$m&rY|$hBDtvT7C=V zJvRA2Q9g)#7Mb>Kv^xNrH!YLBq6PB%;BpM|Y43&#$79W3e{=I`ET4~az6}n4(aLIa zTRX}w-{#QAlf9bU(5BB*S-V_vTYo9C^BW!d8mo;cxpAs3*Pu^1Npn|jRq#C#Qf}_7v_KN3Jf6m;66ZSihhfz*o6I1>Hwo$BuJBRpS=#fMqy3OWHXQPdL;j&d ze#aquZSN%7v(+IF*=6`PZkNHIgiMt~$ZHwF*e%sBwqko% zVkBYU!!~A&X2Z$Yz;@m^B*G*3gwEjOIS>?q{v9Fw^zPfS=cxlhYs#y462|WSr@qwN zZy33W5#tGC%&@tYeY3r-g{fGv)PyX_dsS<>R4bHG6=zDTE25fKMOG6x*rBy}26?MZ zV?2p#@a5bH@BXZRG`yqJ#*W5D!xIV97@bH(mUW^H58H^NX{QB|XSQ>B>_{il*-unk zUE_uk&83a;a4MRBBh_+(-zMW`b&*>;1&1+GD?UhgHn#y80^akajKf>|<-55J$cU5m z_>2*)d*yqu4d_?(&8*)izuDV>d=HWzWc^d}KBx`IZ(-ImPHP{Io7Sic{4 z1gr<5$>K+WO$QMF5C`RlS}WoulRV%B)*nR7M0{HQt*_}T_~wG#x=x6@z;=5#A)hCE}HW}59>00w+oNLV+_#oCQ>xn*vJO?QI6}Bi0D&#(AJ5l^0>{s$0 z8;U=|bEk}F%Y9Bh^)}%@Y%o1|r#y$6aN$mSD)kT!Q8wg#K+~|?=afHG^*-)Tt!FbT tnP3MK_d8r+?RSpX`X^F<>oambZIGMU4!H+-&$IYJdhm-9?|(pu{{@jKGXekr literal 0 HcmV?d00001 diff --git a/obj/fm_log_manager.o b/obj/fm_log_manager.o new file mode 100644 index 0000000000000000000000000000000000000000..22c71507a87038cc84a08c32e5be2d1abd60965c GIT binary patch literal 12164 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 literal 0 HcmV?d00001 diff --git a/obj/fm_log_system.o b/obj/fm_log_system.o new file mode 100644 index 0000000000000000000000000000000000000000..502e14db21d761128f2b648505965a2f5c774dfd GIT binary patch literal 12156 zcmcIq4RBOdmcE_tkS1oK!JrWXG%=1*lBPRGh%T#%34b$)EudwwIxn40lLV7=+uebn z>`p^6fG!!MgpqZz(zr~OHN%$CWi4hFr!vCs;w`{mAAP0?z!jObI!f@+@E)w@2p(6%4V|(BiTfa$WuZz&eJ%>4I0#lTf|Ko z|0>XbgggtG@-F1L$X836&8|hRKo%mIT{yKg?QE+1;Pa`ek4QTcuU!NqD@0Qkbsw6` zF37EV@1BfkN~X)jaE5IR6mGO}H)UO}5miip?;TNXu3Z`78dl3vBkHz02Qy{f!Au3( z*(#G+M`~DgrVb+ytB#4oYT3lFN_`cs;fzBh(=6M($!xiINUIlK==U~dKUe5rM zId?vDP@O66OQU>d=13qV#D=UbvNj{ylG&1IXR74U!PH_Q-ubQX?KIm}B=^2vp4j_3 z`f&<#_0EA+OHvN8DeL&n*t3|^4=e0KTr3je1o8m#1UgqK4ysqZ{1+*gJDDwYCDT_G zB~nEqk>WT|udQhaW4ST?(bUw>ZEbrpGre2j$HpvFy)y~^ipc7WT|AKf)zs8aT5V(M z4Cr86@>mbwUo`xqU+@Ed-H@VP;YwzkV3#)RzQL3owp}8j#RS{X?*G6pbx7KU^*nG- z#@6)B%#4X-+U9>EWyAdT`=@?gD*2MK#6XnH1Tyh9;4*5Zp9cX_d z(ULyyZ%M!EYDvE`-jY5MIh*EO`6u>g{IK^i=BWG%a-V`%aRuHd;8lWGjCE|bQH$|> z1-5AC{i&(>GvU{)^!HLujLED_GCj+iNc}XCNWbDfmHq^MIqpA|eih{tkyGh1@AK+) zeS0$VN1n(OC!f^T$c~YzU!R1YHpE*S_9bm@T-f_uP1z?Jo!NbjYqF85r_}><2NA>i zp8MDJ$@I?p-D_wO{j4BOz5B60k6>+;`G-}+N4nJ}N@oCtf7d+l<~eW#P31rvs#dZH6vXrr>lG&3f-9OSt7VXvi zYk+@@Yt~)kPV&tB$k3Vd3qI4YD)=Q3zoLzPJ)86E{kZPe#|>jDeS5rbZ^o9uxWYf@ zvLQ`3^`7`Ak*$V}@59f><_g_U+wjFN@^7>}?_c?s`1d*1{B-`cO8@-QKS$eMZQSCG z`n=Xc@7P_*>;{bOJvO0@9p{vOIVOhHk_p89#A$7=SZ9nK?;CdTgd6jUIi~F7)ffxe zmVG`C+8Ez2^Z(zj;Qvr8KkppZ7cjoB?mC@znC3r#abJsZ&CJo~djb4%BoLP=_y@nL ze=eq-fA)dCuYjNIOXCfB|Jk1}iiaOw!Qb;y-QUT2Js#eGzZ|!Hcj)8&2G)_`?^B4^ z1@OTJKW$BVEYRoaV%6~V@Lb*3Lsh@OuY*_cwMP2tm%jcteC4|ObVWXHw=EV~KgQOL z__&Y0P9S4#U4By^>nr;EI{bsL?E7Wkn0k3JXpAYx`OC)kPp{zb$w&3EJpp}OYajHj z&UEb3ZM5B`k8k8>v$IpbxHoI~{UeOA<~PRGh)v#Kb-(wT;(DL9C$#-+OkFca*Vzg? ztzW@!UxD9;a(jdedUzI=*~Zkv8-~={J4@6bVa@%mTi=r|c{!KK>{;x!lPI49ehfSf zbaAiW_1eW3ut%4<^?Uo@e?Il$3$rm-lKz#2w&A=p^Xn}1{T6zsg+8j$`*Ql<1dSs` zOMd)qL+;Ti{ZAY)ggh$ijslO%GB53?k>5o=hkR)f{t$H#Lpa0C$@#Kv*Z8=mPMFJ- zu^~I9Fu#FFS4;E)U%ab0aRxX({$hgqi7O!VlJn(6mtCh1Njy({$(eA?5TXpSwZQRX z_CzDkQ9t%HF`^dZKGleC2+=g6?FGeR6Yj>z^k+EZQO~YvJ{aFH#+}rGZxeohfL+Qx zgl&xbA$^`)S@(erHXOJwm*Gry^1G`EcP89L=V&psG3#($JrCbW^B{vbYQeX_V8-SO z;k#l8vd^f^bH;Jc7p1nvI9pvf<3zi5Cl^iMg-*oGci|uO+P#5Pi*G!AGh_$bC>u!4 zfF01!H9v}Wi4^Vt@Wrj~cgB6N#J4BK`>yalGY{o!g=>(fF60fRS{@z8Sc%dS*eHb@eJqi(h!nLX@+9=<$Hafowvp=|ZFvEKg zKB93(A>$4v@Qu6g^+9z%@(A+i-Gk~OWS7W)A98+}rlzJuuqPY~xjO>!z#Z-zJ4!_? z5(tLe(eQS6EFOr)^-9PtjdcVA(T=4(;m)P89Wj8XqaF1<;XsF}x!BUHfTutt9_j_Z zy|b>~6Y1+jQEcssd*bmeXwzAz3+SBocwb#48roLZZ=pN#bYEy7Zsu#Wi64|q>I&BB z480uJl(5_$2tJ}~gkPY$!o4Abz7hU)AlD(Y%(YgJe5E=!cviVPrl~`fCPzI?Mw{DE zw$>T;mYU>@I<^(7TUzdL*94>CSS%h6_tdRl?e=+mjUKPN&b?~Gx9WTzuc!WIcY|lS zr(QHKLyJHt(B3Uhq3 zHsOiw=#2;3f$^x0T}CMy>hZ)e5yHcO5uWx~On90%+~YwVTad4l-5mouNpX*|dHu$? z&#SEKj>VPsKrFO&d91Tr>5X-646NPgRaUNSRPIrNJ)uB!&Dd9MUEstYtikZR zk&bQ&M|)fAr+3XFFunC@gbV{4%g7I*4t>5RRv2goV&>R>a2F7xtX^|vcZXJ5Y(92oE|SCl?@7U)sByer^!_jO~GqtU<)1aDZ6aUHoBe4YlQnq&jXV7Rw8)Q1Jp7mkNK ztJmLO2Zg~$bQc2gc(l8{KOVv=>5PWq+3%koz`=)eGMD&{>O!tT4kJ5cw#v1l-jKWh z3*Anee_L@RpEEXK~mjz@&eaVRj;OzoR~MM@uXC z_-jhWS+oRolsC(r=cBMphF$KpVj2LtTxmryTv-kF1T0G<*{JxT_k;(DzMLnDw29KDMVmyiexFg??%MkoqoOVO&n@ za*^F8IqIV>Cd2Lo%4WOon(WS!a%^`KjGFr~3A^;oNQS;52$}W04}C^l5h+J~3#7gx z>0bqnnG$U=-L1>z`awCir!FSL?wuC9pTaKX=p)0yu=`7CcZRgp>B*H<27ej*Oyyw zap-H+H0gf~eJ@+|H9%h@MA(n{$cDaCQXfD|C!o)qjDEbQ%jMPw<=7AEVlwRhr^Rj$ z>{5<)7f3nM{|7ltL2ms{K%b!l)w%NjTJ*(D`ndNP{V2gkKwlxQrPEi?H(Sc_p2Tzp za!#X@psA1KLW|rvOvX{v8;NqvbyChN8F6gF2$@`>F6L!Y&S1P?-mIkzd8;6Ye-X3X za)SUGuCh7ga_K)%@vy1FkRuvnLg6#mh+UX~n^DG_g4PGd8Dr1XTwJ(8h~E~YQYJ&6 zK^thUcZlCi8TCZFrafO{&qb|XXBQ>f8qG^M#5Iy&j1>J&d)DTY9bWTZoKG{g7^f8b z#P)@Jr`Ujct|uN*r#B z54vQcGm>rv8uAUfLDc2>eXb{m_zVTowU|Uh{+NkR{Szjd{oRzCNL?Sl^Y!EqH$s-Q z+22tUpZfS7V92*Xp7aV-81~PZ_>||nfu0;90D00YO#V)Ap=e3>hre$aH2rlLmj^js ze19sDHkAT+Y27PsVPn+pyyoRdcdq2QIY7 z9XX%uVv&W<9X6lrVzGt4IL}1ME~+eiD_tUn!n)~{C7de zP4p+A`FpX!zXW=xi7rDqVWKNgP9YomYfxT?ea)a7L7yne(`!Iim*(jQL62ZQ4EZk5 zmk~w=O<%gO_ZqZ$K+$&MC( zX{us$|I|XiZJ~M28;SBfr;S8~*}mS7HD8+#+AhKt!rRuEKtDjfK8R(!6U{ zVSm^wX}00`JY}H|g66yHF=X0*$-;lbLjRYAzTR|ZQ~z2E9ktL&3;mB~8gu`anTEa$ zXueNBgz_A$*TM%pPcRY@)d8VwUgvA*Y41_u-Mt}YOEl0M^54$Kik?7ws7F+HXcAt& zlSppv#Y5xx@Z6^K2DXm+qr97mG)t;fSaHw!G7P zwVc*zt;2kyoR+H(6y6O&QL_W9*WG(}^EyR|^|vc)l}@GbEmhfUOv1GNTG>EzbZuEo zq073LF|8v?toyN$QK9vb-IKzRK&Q@Yh$+!fFdXerg5iEVYCzZWm^S56t*tkvZ13yP z=Fy-T6LiN+Ge!)W^Ugss(}tgT?o!C-%$xa)6VU5(Q`34Ip5Bzr_4USEoE~FJM`%l+ zzo%dh745-O>F?X#4NnohuqXeH+2Uei3w#om%L(2G!zm!mCLnfcqQuJ zwpGx*zF@?+O!S6&VM(iq>7uBFL-0zgHh1*+ zwMO~D=euXYZ20twuk}$6UGEKVV;J>q-^%`Z3;P$0h7fgh%;(bD34$;5twMOh$MsBxJ|V|OpsO`&X%udmua&F5Q9(lS<+E&YALf=2Y=Hk06% zu+@X$*4r6TE#aOp*J1q?)#m05LDvxrD_w!UjvkDmj6e(+c07GC6#PcR>uDuE9{C-$ z#Ov4$AHJq)-6-`{>)rza0w2xabPX*oUG?}RuRrW2hP^YE%1kkUyi)M1zke$yNdiqVl(s*adwSMJTCEs z#FG*)04uwND2FWdZ6a>f@0IlXDCtM=okN7219t+_O%gW&Y4<^5GtNpPK0Mnbc1Rp0 zLXLL~BEOs1&kI2I(}}vu9(=0;S?>a}egepToR)Y-;#rADaYk46V*G$?cMPbtlk{mx zUy$^>lD-IJe?OM>ld_)QXY|iWM1RU8mIJB30!aOSVC8n)g^3uiQQ`o8#V76%;w14g z_)UBq`fz=qTmunuO+?6TBJRYv5g~Vs2)Xk_$fbyo`;-W|%S6bvI)RXj5Fxjd2)QH? zc8?Pwf09W1c=XWh6KS6a`3@rFdx(%bPK4eR5po|BA?GRuLau@cIs6=|$&C;pcbEvd z2_odq5FuBN&sOSNLxkKWBIE{$kV_CDcZT?9ct0S<;BT3Z6%uPCHcDJ0@j;1Q68Sw@ zbQiv(h?vI#BIa?Y#Dv5lBEDtz5iv*mWj()tC_gIk5U~>dlXOzzQQ{)RourRR9G7@p z;t3-BI7!5N@`S8EO+-FJ1ph3t3hRSdj`=5I44H00{9_t($O|dh;ugdLLQ$))kmxp{ z2^)8!9-iJyi_{qfeg`v>a7ws*H>iU=bxe#vFgRUlmZUQd&4*nqBA|DOEak~)z E4+5J_ng9R* literal 0 HcmV?d00001 diff --git a/obj/fm_main.o b/obj/fm_main.o new file mode 100644 index 0000000000000000000000000000000000000000..8b1295025d007e04d059cba1c043f2bca85f8a19 GIT binary patch literal 11540 zcmcIp4{TgTdY|>Kojso+o5W5GIIsym$l*WiIwnr21?!8Q7|sa`33qA8@x1nK>?P~n zWp^DL6!jczauLE+%DFvy7vx1kDnhjK=~^j0L1lUopens{brFYJRBZ3PDo}JvrK%tr z;r@PaW_F)n><}t3^7uF3H^2Gjn{VdLn>YKzuAV(EmrLm665B*c65_M=@#LIIx$h>3gkD`1}18#KfQIztP4z=WvDw{HeTcM z=Qm7j9k=Q}Upuxa#Dw|r($dH1T6pH0%+9%eiy?o$Abk144XPj7VOjVD^q~S}W}oCO zREfz&%2i_8yul}Z>ztch6!7f>j}Tst2ln>e4Z8w1gtVc{-jFp0`k?DRzTP(1%k#m9 zJs<8{6rub=wenY^@S|UUsNnORF~uzE17}Q^@8qKJO`28nXUyaGjW1RO#usbR&Q+H$ zc;+Wf@BCThNz*fX)~uSHwC1SRH@WChF~b}bssj_2UIbu25Gs6r+t^|m>bp0Mn|nT- zT=XG6^ou?*ezlmV?zSIW^N4lwQ`(w?p7TsD;v-|J>}|dQeu=Tg(`d6D>&6StT-&sH zxufYLALdbrA7lOG3$uHtO;VLo2MV2u;$Dges=K{w5hdZg;3bp1jj%(Vwp;WKe$%(7;hPW-7ep_8`$^Ha=yB;=ddIX$|MtN@*I2$#1s~_` zov>`v?g!^Zp$UB~^VKzZ>C1eqw)wdJOMHBE6(47ZOY!sc${5h6+XdzqbM)6+MB$g~ zu|~zD$@tMH&+MeR7UjR4J-=e?xF*^5M9sA625yP=aRebM(9hW~}=ypw;(eF=~(Ong0 zu1yqv;g|bIeWw*D-l1~@yKk1Nv=8)fp%y+*%c_Hxp$W(`1j~qY_A?J|8$b-m7 zkeN;+e|DQy6lVeFc>qP4Lw+6kJn}i@01l(`K&GBG67_$-t6D6G9pW++Zl(OKc-wWt zv#_KAkWOaHg`ku-ow1&~a&d5h=c&(^mTrdLI!nO}j_KahXg@g&-f&Erf5U;Ogj;PJo2^WMUm;Hi1~Ap$Sd zpu9==rp$8MdRg{c`7+LBXjkc%dz%N}4wd;+^Pc>3i|#;de)p3zh?S^ZgFY(3qmOG8 zS0FxX($B$uDMsG0Q}eT~iA%r1I;D@Ev3!C4{SNXP*YUz{mzJIr;(LYhli2H^e{X52 z66acLO&b$sWBPo|^Q@S~{ugS(c~2DTLij$x_Xf|n0%!E_JL4wL=?8&_kdN#gH+zwN zqWJw_trtv_SXx>VM~94|NIWU}2ATrR>Er= zs?0s4U!RFx3=77J+zvq$fA{v3_ zmT&u8o7F~O~QC8`$a;^7NyJ}pU+_kQoTsN29 z;=Z+PtEuXY?mxkxbWdn?U#n*0~17G zg4+?9crqKy# ze=86F>m4Kew4#~KMKZbJ^i`uS>R0e?SzSCCN0c*}$WvInDY?ca@_`68w`w)TR*L

D3YmMta!j^*&$HY6q@gqp`l9XKjWX?Od+o4ymKT01X?u(p`&GvpK_2f8 zb<(`uP=J?yMpbl!cL-%&ukn89?EYPWf1FQ_kKrMYew{(K;-@;!!yb2FowU9EP}uDy zK+^G|pW5Cjl&x_ndlz8Oo><59F0wTa8;|z%n03GBp|kg!v-Qh6Ro!m`jL~+5vUd^v zZiB3owpRg?-QEe<)9a7xSKHg7?3F2dS5_Iv9?45TW8-lg`dQHZe#g=8^R{tR+xq=C z)vq3h2Lb7UPA6?|z+rC+_BdY7FYlD~IQ~W1)8h!=pe;$%rn}%j%EfVz$8pdWlkT?z zJbV1!u*Hve*u{ROz2b9u2==-yOY)z#_je9^7hrEEC>#f$S#9qfWe;Gb{3_!pNM7;z zAdlmqEhgRXhmL+dO{MjGtKzZU5_r77*U#^(u%~T6T`d2v!(Nrmo?r23@0&2hn1gPm z*H^K(LGgGVW10bv-$Xjm2Z~!AymN4NRFi<@F$Wbdpy~p6c$!t2KwHfBDjs!AkMkk3 zCGEn4;Ng#3ij~M~(*jWQ_#A*&On(ku#HP?ZqK*m4GgwS#)(CMI%3)-VfzK(|o~^kE zZ4shDZ~my$_E21w?0S#*uO)k>yEuzd>n^TZEqevRZ%ZD_7b@si*;VcBPYC_3T(%c+ z2X0VpIah4I4Op5tkJX>`Z45no>B4`?hmgrPfTdJ#wVx|0Wc!OYIf^o6_QUqi0Qs$r z?ZuK`26BDr`nMqS+gr;EkogV%qT;VXxejHS>O~dgQu2z8kom11fKrdIt~kNcKfg_8 zKc(c1UzH>N^tzPX))Q)%*IIs;G|LyU8@u!J`P93$Y~i+kp)0j^eE&Pspf2k5Bx7g~acghuFzw)OYeAiXa&+U%(PT4CSQ|&o&7k2EEkXcS(jZl68 zavEhV=OOd=MJ>-j?#6zh+rJ0-Rmi&jKOk2lzFPht$YWSWTK2;BC)hi+d^6-jSQc7t zfXsU{E#C*3_hnj!tHtETjok9}QeUiN!7c6(`_aCXmI9UmE0*6&waw8)42-06@Xa>ze$$WJ-s z35Wcb4*72!@-H0nn-2MHhx`#_?pJ<{Wj$8e7moTGE<7Y0U+}b4iQP)3j^lq&$y^s( zvHv{gkP}MgS#K-$lM9aa7aj7yLJq;7BVOsx9~|}Ga`r3}`)_i{haK{1hx~Jg{GmfG zx4m<(HDgSbpHcrj)Sr_}`ozG!o)q*dF(TI=d<#p>;>mbZ1Q z*UKBe73*6QeF+1f;W0yczKi!GiAWzl_|y2*Zw?6f*@Ax^`*(Lg^hm(+Y4t|J*xU2a zcRG3uBRkw@JYWnM`c@Nx*qJp(;?aRv4n|fBSl6y3uCt6>d?+S^lQrVeoRLnA#4=Ru zk}~c(t?EG5-~jqlQPN>_b=SIDX<4@#Nk-*ut2IH=3d3O4w`2{5Rff&3k%6`}LCLXZ z#!_rois4L#*A>dHo?FQKi%X{S9$a)C=IuqtYRab35cQCP}YiGa91Xl z9Uh7qiB$hFV*Djo6+Hizx$Z71i=Sn$8%*xTTYp)S50T ztrdfjL=sjhJ0gd`j;?ZY#O~w>Dfg&lim2n>DfJY>x>EG`zR@-JOs;l%PsD(S&R=w24c&({k&wg{^)JXb{ktg7sk=yWdE{8^x+;G@o38FLH`rG z_|)xAB~si>RySLGQn3u8*_1IDNk$Who>~(K7+wKtMe`>c>$lCiu>AI@dsv88yhG|9 z!TW@W-!KM=sJFhI@ZLK^`BD5jMf@J_*MJQ;%jJQMz*ngMKF)(gd_bKe{;~Ysv+l6` z9kdK~=AmzROo-nD8-bU|gWXT4$BXPT^}x@7n|~m`pBf&AfOmEy&;z8t8b~{})C22) zwBx59A8z&31Mvff#c!t`yb$%kP9XW+)c4B!pGM$8$h1Gm`UuX$#6JA?18l%qbQIVK zJV$*$#z%}|d_=_SBCuhT5bpyUfuAWozsorOdLZk!0a?#8V_gcr9~0rvIbs@iiBBS4 z#0=s@%%Tm>MC2VJf;UJ6?*uW2pLvPkT_l2cg$Q01`Xe-qm{&NXa8}`*!g+<474jmO?R^UQ{aJ>Gt&WJ;`iVO+P9o-No01z9 z28gwIK9#&vVY|YR!cK+V3VRfW6&@s3BaTWwLPY<)#0|L9SNcJvPY~B*o|HbPa8%(5 zg=0k6nNad+;yTQa(w`yX!+MH{Ien3cjIdkdu2TpQcVUfFuTdP7=X%Nrfu;8=+@>&~ z5FxbcLkhcXD2~c~?Jlg5u+r0B-5~xU-32G`nJVfAkcnEq1@WSskase5LvkOZd`0Pf ye7-gR4k(%6Hxr+8gvNT#5qi<^gtXrXtfzb&b*u+=0ymG~AJSb^BHhs}#Qy;*Z#TC9 literal 0 HcmV?d00001 diff --git a/obj/fm_menu.o b/obj/fm_menu.o new file mode 100644 index 0000000000000000000000000000000000000000..d9e04d25384aff7c7efe79904b344ed19d94c8ce GIT binary patch literal 10576 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 Im`8~J1I{2?tpET3 literal 0 HcmV?d00001 diff --git a/obj/fm_mon_setting.o b/obj/fm_mon_setting.o new file mode 100644 index 0000000000000000000000000000000000000000..ff19063956cfcf9b770702e62b9c3c4d3da28c25 GIT binary patch literal 12776 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 literal 0 HcmV?d00001 diff --git a/obj/fm_reg_box.o b/obj/fm_reg_box.o new file mode 100644 index 0000000000000000000000000000000000000000..6953a339734fb0e7ffcb925d134cc2fcf8d64453 GIT binary patch literal 13624 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 D8_H6^ literal 0 HcmV?d00001 diff --git a/obj/fm_reg_fpr1_1.o b/obj/fm_reg_fpr1_1.o new file mode 100644 index 0000000000000000000000000000000000000000..f9095719d9bca853b6694b95efc36c2f43a5d46c GIT binary patch literal 10228 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 literal 0 HcmV?d00001 diff --git a/obj/fm_reg_fpr1_2.o b/obj/fm_reg_fpr1_2.o new file mode 100644 index 0000000000000000000000000000000000000000..5e609b119566992a7d9cd1be4b898697e6645540 GIT binary patch literal 10180 zcmcIqe{5UVb-olSSy9xPR_xYs6o+w?RIw$7loeYsyoQP-+esXUw%j)Jl0H!sCDW!z zntZb5)mZ6Dae~z9jKoOO%#E19eV8*|OPnx-7(Csa}XRX_bd9YyNj}@e?7! zCASbw^&(%8a=z4)`_UD*$d@QjirKO&kT0dXrpuIdn}1(iTr-3^d)dvv2`hb5>GwnS z_!deb?`$~~korR56&4piw(z|9Lc79hQ~WVSG=_e31=tcFKK}ROViWuNFB@(EZF@g_tjIXAE)kk7Uq*b~B3wY9FDH<91^S8! z_`>*M?B3t$Lp)mZrO&B&F>arO{cO)TtqeSE#pL?(T=8-p+vQ8WAI=m5i0Rgir^|0G zpDu317!msuWs48Kcwx&n+7ikaR*IP-@iZ4c%mrVlKXF6YM6f@;jPfZtJL3|p+Ph0+A#fzv8;3LfQ3173orxu0^6}% zK+ltw@u5sVb1kRK(-@!T@C&a(| zo}m-P28H4A!8go@7w^cIZbf`t^GM#AD|0^GX zwjCEUS6J_cjpyet+H5*u+0<>bY2}S<3Q3y|)!6i6#ioTr(x$6HY13j)sFTIUD@6?{@^45*h<@Hz(Kk&)9br$tppYvEdXOMpzeC4H?;#I82S**2Y zpWJI6#a=YK{F#b8ZpkMq^0yuJKXk|+K<4@9#aa_zp(q*#dH~VdT({=p(c`?n__B>^t%{*_&+Z7LiztQ++ zuAPOT5%4!26uGP5uRmCydlm=J`SY*m-UjD6f0^?4Jvn_23vsGkk8=fQYoiFAvgT#I z*jwNpdL3se&s^dXUhlbHk+asHNAUa(mr!M$VQi!KTk2mO=={hP&KEp57n-rRHu9VZ zjPb|<55qN$T@?Q|%)8%?%y(;@{dKG&z+BNy)9_$I6E;r>*EO_$I72Sc@Lf@hD zh?QtshCZ60M;n(ZU4i&4OFswvYK$6lCl=;i(^uZbyrhku9L{01{Rha)T!%}4x48J6 z5ML=x9nTk7{`dGkz*%O^VPm>3r_V4?s1s{6UwZBFDV$AHICFUxBY8vCnSAWer^-2` zX{2W#nkt_}@(TIwfuXU+lYDV;QDkG$RC2@@OJ-7ugkOm9)W}34=8I>2$&~3Ep2!~c zi_vt(7>k)kER#uPjL}47jP+(_B4*Y3GO_GL!rbD!d!$K>jvJZSn1LoiqYHfuk9BtW z)5$URcVNHiH_cHoY$iLSofB5E%#YaeW+guyi5}E#skc8h9@8>9u(D=6-6=bhHOrzx z{K@YN@%6))>)#S0_&Y+}Jp-Q?X@L+e*a%)l`G3anQHHX+Q5Ha=ts_W(dlWw)mQ(Ij zdArV1Wxgf!wk%PGA|bZ-^=DBx)=Z@mox8UCg8pESKj7>1ZQJu`XV4$;cirpj z_HXugiQY|U5s5{H00Ibf_t^=R@a)k+uUpG z*10-d!k;}lZbpW|&5Y#xbuJT2_|4d)Dg4ZhM9hfr4`;K&-@E5AKg!vPHByX^OiGbW z{KmdrgJv*b?2KnkV>ptHJ-j(P7B|MTV}p^02Lr~yK#%d55lzG*nSsMLM61JJw{?vX zzcGTgyN8C3rZVIGT}zwhP*}S6C6sgrgXX5gv8b8KJRA-N*jZ}$0AvOxh`H5A_*gI#xfBL1C0hZqTQZHky|>HpJjhbyZ_nx z$Ud!TX3a>(oJjwI*Ol@mtgESuC*z26CKEY|$(xdMTyidmpubxeQ|zV~O^uJol2{bj z`C|UCN$d5Y0D9?f zs)`Sw7e-#!YyKe0?Dn05eH>5vhYypAeW#GO;-@<9fYIE6HEFzED6r$Teo^{IJi0?Y z`g;P&@(0DvqL0o z@#FhhrC*6xS(iUWqkaoX{%E`(I`EDGuLmmkB5}=XydNt(FpJtbiEX6)C`rA_`k)^D zAQnmY`=O)XIoo)wReEf<2tB+%RrZ4b@H7UBEBXI%;9aoc`IH{X06R z9{#1Jgaq1&|b$?>Tsm1dF?_~=ta>bR{HY}a4zh`;>9f!1(i_pZg$ySc`zt##us z3AOR!j$S1>RV$Hmi*=5Ar`#a!RrZWP-&HvkB#c|!X-P0^wMk&?M*ufzUv-67x1i3Q@f+&b(B2bIh++MjjE zMi+E(7ncAy1v05%pXmsMO#D|`*sEce4Q|G35{jKm3Ic=-`TsXZ^z?%0-|liQVZfW3~w*dgT_Q! zy)@uzYNnE`?TJPb30B5!kfWK%c+3XL&McJiNIba|O0YXIoG{Gzc+8M(AK-gNA~GCH zSg=+#Zq>h7?N8(8?hnH1zRmxSsxY?ieEgx_oraN}7&aa@@NQW1d`NGy#*z34ULU11 zSwoved2`mXFk{sPvwU?ltVaN?%!1KKoF>EJ8@n{no#b;EqY}s(j4tD1Yqg}OwXKdM zM|3L-g@&@39hJiZc~@m@`|rm~l(8?kiI%4EkeW3{VkX{g1>DKDbYE%29%koWl#T!mdR`J6};^A$F z;{$~1)==`f_pnH3;z_*bqH1Hs&g}lwk!o{MJD?kdVOS5D#zgW+9O1&uhtmN9*&|iMHWN`k!Wn#4GLD3+^EiA& zaDIzK3M_fD8HkAEbtrX|!TEKbJ&k=MiLlkEI?{Y|tQq>CEci?x)W&1ujcCLDHpS7D(}L)M2RL8)Qi&8dj; z_uwx@EFYBL|E+uF-ybQTWBHebxTxyiBmauL$FzP`h-;Lez?&X9{?5TWO&$7aB*#a0 zv*KRGSE~Be5RljOkRcNX#a9m#m|8geaX%za!VmHk{2)&Qhx`!EWbzE!lS2>x!N}6PMh?A3V7F#r zA35}%Acx*Da^O8n4!twv&^t>Gy-&%Zw;Ja@_1egx$8To#8zzU|OXSeINDjSAbre6K^|-$A2HYBx z_EgI6!uYcMfLezK<(m>^Ykh%p9aZ#c1c{FkAp3e}e;f8o{0$S*j}FLfDDQwA0>Aw* Nen9K}lHUVo{trvQ6$1bO literal 0 HcmV?d00001 diff --git a/obj/fm_reg_fpr1_3.o b/obj/fm_reg_fpr1_3.o new file mode 100644 index 0000000000000000000000000000000000000000..287a2d2f66f559b318dd32921c8523aba9e20d75 GIT binary patch literal 10288 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 WdK>f@rIclrY)0Z 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 literal 0 HcmV?d00001 diff --git a/obj/fm_reg_unit.o b/obj/fm_reg_unit.o new file mode 100644 index 0000000000000000000000000000000000000000..7eee74946683ffed0f3752c753f99bd7c30500d5 GIT binary patch literal 12336 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 literal 0 HcmV?d00001 diff --git a/obj/fm_return_card_manager.o b/obj/fm_return_card_manager.o new file mode 100644 index 0000000000000000000000000000000000000000..3c75ae8917a7f73a9191d82b5d0a227c69c0e5d4 GIT binary patch literal 10884 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 literal 0 HcmV?d00001 diff --git a/obj/fm_return_fpr_user.o b/obj/fm_return_fpr_user.o new file mode 100644 index 0000000000000000000000000000000000000000..501df31154d383e375901075cf2859cdd3ad6e3f GIT binary patch literal 12168 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 n4EBAP?XBJ`?XMma!UuT`ap_6c(DB+vu(D= literal 0 HcmV?d00001 diff --git a/obj/fm_return_photo_user.o b/obj/fm_return_photo_user.o new file mode 100644 index 0000000000000000000000000000000000000000..de2bcff61b54cca3e1423fc23b596c867c11793a GIT binary patch literal 11344 zcmcIp4{%#WdS6*eB8(wQ;($YxAcCR3#1@j{OB|X58Rw5VoM7S{N7K+}*;X7Uwj?Au zac-D91v^fL!#xjpI10I1beL({GJ|R9T-pgUzBDcFH0`B@-esx)GN4Xu zkmXg7Z^yF~5BbaRtiV$(yaCQkVe^5;6mzzd)@+zPgq9b1|M)eNp z9f8aWPhfN<%cxIRjOtsV4+N%GI((TG&#oIW%Icx3_e>c!>X5IK`C8;_kymZQHzRrQ zd&MOL{zTgnA!>o|+#ANgpaK` z`Y%Lh9x?nyn-6|_Gx^(O-xmRI^O*I~pL})TgyH9BOVc@D73*d4Egz2O0*oX4WnXFc zI$~wIWBxL3JLpR&GgmFfbL1%$KKSel0B@BY~;KGr@nbgzp=gH zBkv{jRlKB&u1wzBhM2}-qwAmbDlx8~zkSrG*ZA~k&ed@uw+#B_cvj$HTyAWh(ibD< zuRV~-GyZj3&3>%?mrP!uucH@5ez7kzcP>6U*Z5E-f8jloPp+$LTz~VT$)~*Ev)zdG z8+U>e$jq@G^#VLs+>9G#wj1zH>P?s*)g9xA!4q?@J4EGTpy)Wh5@jo07?Xf^RBt~z zr3=h;`sYYz^1qCp%q^BSehD94zD#}=bLHi`Gx=4R9}dU(HI_TGnf$rzsL|H>wPqbR zY_e@P{HqH5NGIr;q1r(ay{8^E=Ch=_mYigvPJYPu4k?Jt=)XW%N(^y8n)% zuhpO9>%J0SUn%(NhF^@KSNggudMfA0Wb##AW4Y`%mKZ)W23IbK{C>1C3_sT?KV9YG zS?c52mDo3AJU`FJO$+$gd!jhbYX(o{-0)3}N!xoOKW6tUYsQb9(y=b}&HE*Mt6spj z+0mkJuOW6Wi*M6*zh>Z#oFFx&b@`^-PILe+_y^$_%_i~^o?t`=7r*1`(ya?ZTNK( z^YSkR)^U0q`}?>t7jK!#8}|L;hb4X#$LUOWF&4wmnfnC$ zv-Ka$F*?xnk&))^T zao(bB^L(DcnbjP7mzczS>A=1qDmfQeN1e~e=lRQlHe5JIR^c4x=D9MInRAHFIfN8v zht9mqvtp(2jI0C)`%){;jUzdSCz5sH>@Gqt>MhHr=Mb+-$2~YNdGJ0H-C4FJLMLF; zoRb1}oq=$+H8?%@HE>6|$PHsJ>!kc@%QL8#&gR|l&*d}Myvz3^o(boc1jn-ULj+!2 ziTs_yGpR44t=G+VD__T14fVJ`8hs2*>Xn(XtSj?;&KZbgTc4RmtVHD!v{4BjeOw~B z0`XZAe;)RWF>S^~@`{hlLt&ei8YaP#Wj-5c&wjIllhlh|aTo0N8}5xqU?6ipL|&?+?T~8vGOr~P7fri~X zeL;V)*&pyV_;&1htRd(R_#40GYw~aQH;R@`s1c5YyZeQs9@#~k8(PHT$|Wss$1N3= z&ML=pSG8lM<4$LdW0m8siq+1w73&=J4&hH88%%|}fvJRv2URW+8Stkf!ztlst~ZG~f=~!O-f_GgWJb0goZajPs^Re@`L8o|+{TAL{3-5r1cQ^8UcP_@m#Qp3B-jph_ zO{Ud&aMe^uH}1!684BqiIegrBDAS%gbL_npXA{UODSO;It@Z*NiuLJ>viAV;w5#kr z3wu>`MkZyC@nX9;ZWxI?c|+eCMLn_KwgzAd>A^bf6efZZ87aI zdGY5gJoZDa1=a2&wsvPN{ovVDwfi5kUDb~^wA-#4lRSXvv)Q`@d+aaAm-oiX-oHwF zsvncLq0o|)>Fw|z`9eR)V?St%N%f-zJZtgQhZJ!C_8GI*4|bI6;?W%!>}BHH^Sv&#}GW{7S1kJ3^Z)7vM z#LtkS{0flue+{fN3-Mbk`0p@&OLM*{f3_9|*t8e2$c3uNIN?=kyy;~zIgJ%*m6zJ$ zS2}5(*o{l=somMM;WYm1X0=ysv&WGrCMR~qQhREbG&#7Wr3@Mh zdMI7rwW`QKr?_7{jrzq@B49jt+AJog_?@DFoD&hUCMRZyH95hET2$OeU$V)6Zj;}# z$^T@Nb2hocvMJO4eKt8@llh)eiTo#Ra*s_Ou*pBL$$w&#|I{YG4Vn9m4{a^Stax9R z*F#>1{l>wGA`|^_OPTX~9rlk^HhI02c{W>z{or|9{TFTWE0DX;{)F3X|8H#N@7v^G z*yMSeT)#+pYraGF+2j$M{I*U0xmAW=SFJKk{|{u|$?ivf8Ba##F0}kT@wliB3vFL} zFo+u|+?Dhk)`sHpW&od(saRCh_8No$ZzZ$?iSS^gqj0~#k}XC-WVkp8_g?P^ZvEN7nv)iOZna zF$Vd|+;VFBdIvg;O2wh#6(g(^6+u(+mENBXMg|9CM>x%*M-Sn*adX*j_Fx62BJ?j9 zG&UI2!|+*xZz@P=vW#mymMpp0Ofr#V9eivI*oR7Z7Q-NKvRLdN4EIG!xjnr0H2#bp zY_zcDJl75kMSDsr(TA^FhzDYJ4|)!5;e=|94aB%#G%jeiFkn~Tv9p2^M{kVT1K8^on5~1%Rg2(S6`Vl9#!GGc(2yu$#8s6>1E_}NJ zH{6MDBVax7GWD=~l?b~xh_L$!kn#Hz$oSRZJxo2nli1ESAj{i;EYGm~kPv5yhv7eQ z0CtFjI0xWNkoOc3<)>x&tSrAQ%d@iF=Qiu_C8B;W5%o_I5m%nw zXy-DKe&c(?@S6x;hzMRA5xfcFGnlW$1E?qQx

YQeQ2xPU2RH9TIyb4oiGNBEKIi zHe#L;F$SlJSQi;0#`X;v+@gRJLeSlbxxl380*kj&FtjCymq@F0gh4GcLPhy?K zfW&5rA&J|Fu+t`G*7x?{2WkCkvmI|YbdU>rpWL7N%)1TmK_M=&9P+Ovdboa-o%^6< of`3e0uLzB?UaKibO#Ah~TFMEOu^dSM)+F(Rw0?t$_csXfe`E+buK)l5 literal 0 HcmV?d00001 diff --git a/obj/fm_return_pwd_manager.o b/obj/fm_return_pwd_manager.o new file mode 100644 index 0000000000000000000000000000000000000000..b0a8332d1be7fa053875d7e3f76209ebb6302fae GIT binary patch literal 11036 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 literal 0 HcmV?d00001 diff --git a/obj/fm_return_pwd_user.o b/obj/fm_return_pwd_user.o new file mode 100644 index 0000000000000000000000000000000000000000..a86d2a2c2da6955d92198277171c6d907dbfd938 GIT binary patch literal 11012 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 literal 0 HcmV?d00001 diff --git a/obj/fm_return_unlock.o b/obj/fm_return_unlock.o new file mode 100644 index 0000000000000000000000000000000000000000..764c8cc8bdc6f8d842dd2cc3a9f017966a2e54c8 GIT binary patch literal 12088 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 U=zie5-S~sF40ohV-|~t44`#-1RsaA1 literal 0 HcmV?d00001 diff --git a/obj/fm_safecheck.o b/obj/fm_safecheck.o new file mode 100644 index 0000000000000000000000000000000000000000..4f6f4f8dda0b08372e6e5075e25ffb0a9f313487 GIT binary patch literal 11604 zcmcIq4RBo5b-t@zON$VAZA(Oe3=44*#kQ7RSw=FWiC30{?Xn1AD~aoY(B#cA$Vqn}*J~tvk4_(_tDj)wJrwopFmhcp4^2%Sy{Og3^rBk`ASw zs^53ty{oqm8A4~cqr2Zd_nv#sx#ykx^X}8*?V)=e4u{amA!@}6CB)VBvSm$!gj%sh zwO4??5qT{#`PU(DK(18uO~7j8n~^=iy0>?|dHxLPbMcsXYM*7 zZt;6(^DdEDaQRQ=*|tf5_GA`Vc8E-F*PAnop2=62Jc^I?zg%8^rv|chy7EBX+pW-1 zyMHz>5}AeAu9H%hOY~%wp1&-E4)#sdpUkfj`*X1S$5%^cC7*zvR_M9%%&SYf-T8~z zXFWo^(*(wskmpN;cmoQ%ft8@o@0!ietv79#w)!)GIUxTj#pe(S+P^;A zaH48TOs;#Y;bcDRnx?+RP3TvG@x9e>B%fVg{xNu@j54tySGj(64YIVylsBFKXXv`p zGMj&I-E6+&#_2`3m@MeK3K?>2N?%vwi7F@bb(NW8dIkNoEe9G;%C-Y#M@;#uPq(V? zX*`+lMjLJHX*?ordff$K6X7dr)r~OR3UWVO4)ODgw z*T1#HwD$)clZZ9bZ!SDTwlfP6k@4UZ;*U(aGxylqOzyvym&-NngTAYX!K)rq?n&r* z53~qoa+gr&I<8_9&tn4PU_Vy|@!OMG7@TzE#M#UO#9Wy`?7K04L}o_ni@+YY z$DB)ySNfDO6roSh7E-qNgXS|0f-Zip(|H4Jdj52wkVZa^yab261iXaF$=HvS32_;; zmoX27ZSQbSi=Y|9A{fjG*r?-F#}Ml{jxp$G*`?x&b6vNcQf;2#t4mt$y_m=F^+F}a z%l;aL7e4a_a~{v}yqH6~|9IZvc>=O$@)gcUiIbO3*wSP9>-2CmlQ*Y2&UUo`nicYE5U%$F*`gVHr+PUJ()C-N1Y zGZ^cG3%^7RmjXrS6IE!da>4g|YNqp{H0B1LFYQ|!dvei@m@ic_D!rN91^Dk(bU>9trU5L$cAs)<$ z9@_P6!LD;D)2_K~vw7NfD*mLjYksHck5jK@a=noKwVm+mMr9xDaRg_UKFYS(h85eY zKgPB{yM}Gm$~M~7F;eWaZ`y5|Gkvx+|It3XjJ-np?BneE-D}u2nOu36W3bC*d6tnM zirhK7ZP}0aSMw*ZD{&3GmclD`={Wd_-4^&sh#46(t~ta8=(BV4me@KfW9tm|jF0tG z(2T7Ii|qMMA+`=2Ua{vC{G@Ga!SgJNC)mJvKZUvaQ888htJtLCJy2xRO1uv?i`*Mn z`yKGhf$r)2pL@-Dbph)Y*QTeiZp@+lH1Ird5?FZ&XCACca=r0#T{QRp>#)WLZg_IB z!cw<+mAcR>b;GOF{f?|VS|smJR^j`5)N%c^CY-^9KI;W}@U*0(;wBMtlsYz{4twq= zO71^(JaP7{nAV+6?{rK?K)k%OWbzV(VQm+efoIR2p4{pZ;`Ginlk-5*?*W-SIJBJo zW7lL8*ZWSaqvCje4fchm$yePXcwFu)Yq0-wkN9AD`4-g6{eiO0Jv6i6DeQ|U@SHjk z!$O`#*hlXtLT_gndvb!T}tDRG8tN^h2Hs|X%}OvJ(w*ax{ze>mG3IJ@vg@J{uR zH=Hen9?;LX97ey%EcPnc;x+dSm-iI+v4yh0(Jbu{{%=*G{2AdnkzYeu-!=7?e;0cW z`jvalJ;vofkuT32&AKwj7M=cRw)OB?_)3(QK}R|GXk(e;72-s`EO89-SA682Jer+z zOfS8LxS@@%$xM#+{RniKV=RYr^f4j6lAC%Wv%va)!r2RZwTv-ix@1!C(XL<}&lI`8 z?U=&eJB2d^&l<>{pgeQ5U7X7AK@K5zhNkje$R1&yS@39NtPq!%mqq`ukqY-m`v#+Z z53#Oypw910j0~`RXfW+dr~5^LK{ecQNQkd~6^F(rgqRx?BJk@%d~Sw4gwSpI-@v=a z142-0)7OQlSQcVWQi!dPd=L1%$e%-wATyD#7BVUCzF{G7t}SG?mqADEs1VzckB>yhc3)#|*cxAW1b z_BvDvvAebP9&c@5GM-AM;Gu_uW?)@cDi9U-UNk8h!Pm7zrR8NUZpU>c<<1JndRL{R%JCUzwc}>TEhV=)Z!5XevDG1bsfUNt z;a*@mY2u(RC8IH4Iy#XSK9(ZkbXfR$Qz_wV*>}GW_3XtKlN^dnm?XRSjDsEf(*eH` z8cL;&-f$|qw=p#^WDKVU_J{ZG_Z#i)O~(C3Uo09_5%4wWYLX2k`{KjH(Gg6Fk$5`l+uiZy zItauXD5pU=VWZ0Y{AMa#PjW!7tXS0OKLag>%ve^D>)bYvo5g(?#?Un|PsOMFAMxv$4K zEbW?aC+e*Bb-}&^sN?wP9&O)ol%@Za;ysWD)U7fb25j;! zLmtP==gWI#J&u1=^7J^~uh5cA)S}yAKgxx1kdNb_EGDhD1$rlKi*>(^qTSt z^HSU(M4Oak{%CpMx5=x(!J`Q*90%vDmiI#?4$;YALU&SL9`X@GId@<-Uh|T^B7YX z__#*sL>nmQP8;7-;5(z8fp+pS2Na(lWu^v99-eh|Vi)Fn6rZl|fSQl<0DOh?d*BOODl{Ka`-IHr5KP%JAvUAD51C_NoH6z+-NlJJgqYBaKiafB z6pNCz-X(sqY;ANFo}yXnT!~s);Y4Jtw{`%3m7*iS640A~Twl#ZYgdx9XvWa~a>>8K zQ7+|EmYH1Q3n-9|VX#{MoY{z9m*nSn7BiXpUo1GrZ0GyAZf`+>G%ce%yw=F~cG^rj z1zbsP@fZlc&p!ub`}csI1t)G2e+ZiI`HUxR-xUg%$<(jk|EYD8Zj#8SxRRV$^^5&m zyhu6a47BpEwaF_EQYTj5VtINsHf1>FS2(M@N}D{c$ScW-Rj^o|UKLFqr~Ha%<-ge` z&!qj_cx5U$N>Wa&PQ~(XmHQ(b+mK5NtCwU){A@G}>eq=CtJuF>!B&z}cx~<8l}41D z;!az;oh}vss(SD&bF38~wbE{=SX=D;xbI8~t+|y^evP679RmMtebXJ>(tjdPL1Vw)O`VjpGz%V}*F! z)_zpcwX%Jkc-BUrRy5CwcVfMAuK}Yh4YA&sfmiOR zlDva=A+c~TUhWfkt@rtbFVq?cdm1W`CWnvxCm6xbV|z+GQ|d`t|;aySxU zJk$q<>iY~{H5sD`IYrnpItVUAw{m}=DH%r{ekaR(NE7%EnKG>pnma_4ItjKn%=t|e-C;aXG?Fe^UQ z+r;7M@Nj&LlYM0T5PkzYibicdTj|$;Tn51pM_Pi&tYFUui-!~ORMGWriiu3tz{fg= zHL{4$A{fkfTOZ;U$Ha6}|w z8A z1K)cUo+qOJWrbN{5B>)b=cFxR*a_SU^a5*oasNPsyiOwg)=fnJ358E9m?8Gz zf3Aq|=V^s!6rLr5@0_AvQS^C5&nbFd(H9h6RLFPZjS=_-xMc&rqXBE8c;^6a1^q7R ze*CYe!V2gjU9GSdxDj+S=>fdA5eM<@5x51H1tH*8;M1(fc%LI;ye|>qXP)1v_Y9Ew zE~-zSBhTEfK+2iFYybd5Pd_AcC)%2);*&kKq3fh;i7V z@C}9UD&%E2+bb2;D&)I*Nj>Be;qxZq-H=a23br=zemFqH z`4#3%IRLR4b3~>uoAso57A96J^eU`X=(nIa1p7!sXp^dEznU0+kT&09-lx|*ggVfL z`rFNQswQFH@6;T|yDi&6UsdSgx}fE3LM0RIWMUj*h%yeTZwtPQQ~s9U#PeW1Xm;5O TItbkOD1MMOZ#MDsTZQ;P(dQh3 literal 0 HcmV?d00001 diff --git a/obj/fm_stat_box.o b/obj/fm_stat_box.o new file mode 100644 index 0000000000000000000000000000000000000000..20109bc0f15852b354f99525391fe690af2dc489 GIT binary patch literal 11808 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 literal 0 HcmV?d00001 diff --git a/obj/fm_stat_bullet.o b/obj/fm_stat_bullet.o new file mode 100644 index 0000000000000000000000000000000000000000..14181404a387efd29cfcbc440742e934613df03f GIT binary patch literal 9588 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 H72^K@pFYfF literal 0 HcmV?d00001 diff --git a/obj/fm_stat_unit.o b/obj/fm_stat_unit.o new file mode 100644 index 0000000000000000000000000000000000000000..7f99fff4710cb3f42379ddbe0f745b9555072146 GIT binary patch literal 10848 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 HRw4cm)<=I3 literal 0 HcmV?d00001 diff --git a/obj/fm_system.o b/obj/fm_system.o new file mode 100644 index 0000000000000000000000000000000000000000..1ed3c7c56fb8b1e0daa0a4409a4cacbac37db4f0 GIT binary patch literal 10600 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 IkxfGU9}Ou6OaK4? literal 0 HcmV?d00001 diff --git a/obj/fm_timing.o b/obj/fm_timing.o new file mode 100644 index 0000000000000000000000000000000000000000..c3575c3252dede814d79fd354a9da39b64a79c00 GIT binary patch literal 13772 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 Oe~=!jmbmayA^s0UL?f^O literal 0 HcmV?d00001 diff --git a/obj/fm_unlock.o b/obj/fm_unlock.o new file mode 100644 index 0000000000000000000000000000000000000000..7e915abb294e530e279bc3a2fce74f549312dc31 GIT binary patch literal 9472 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 DDx*rm literal 0 HcmV?d00001 diff --git a/obj/fm_unlock_pwd.o b/obj/fm_unlock_pwd.o new file mode 100644 index 0000000000000000000000000000000000000000..898786ec015a65ec22ace3000f07a912fa6708c0 GIT binary patch literal 11180 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 literal 0 HcmV?d00001 diff --git a/obj/net.o b/obj/net.o new file mode 100644 index 0000000000000000000000000000000000000000..f0f1f7ffc0a3d4b8a6e32038ffbfed180319b04b GIT binary patch literal 18780 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 literal 0 HcmV?d00001 diff --git a/obj/pinyin.o b/obj/pinyin.o new file mode 100644 index 0000000000000000000000000000000000000000..4303f6a636c049107f59d7f4d2caf4b6f52542d9 GIT binary patch literal 42380 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

@(DryylXh7xCp3^Y10b>8uH1 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 literal 0 HcmV?d00001 diff --git a/obj/sgi_base.o b/obj/sgi_base.o new file mode 100644 index 0000000000000000000000000000000000000000..af3807b9d2837f617f8697aa6d8b0bcc86b44dfd GIT binary patch literal 16008 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 B!GHh& literal 0 HcmV?d00001 diff --git a/obj/sgi_base_box.o b/obj/sgi_base_box.o new file mode 100644 index 0000000000000000000000000000000000000000..1f601bfb9bae6c7c025cb209d0f5687d9bd098a4 GIT binary patch literal 3460 zcma)8eQaA-6+h2T(lqso+of7aL-&e`6h>m6-E<9O63*JRW2EgPZ3P;CIF9|YnK`zx zU)F#Sq}dvcso7GkEfU(;D=HEilSoI1tSCz|P{m)Cit;gpsPwMA7fLsYO;n>yXy$j` z^J|=xj~(gw-1BkIx##2F=O1?W9Fio7T#%@h);OY;I$KlQVUt$!(>>%G&lc|?YLL{E#ShEn<|evmwfHYu zu8mA%RxRrlqf|?V@F`rcG~iOvK|j9FH;v{GYe|ucLHTyKav z1uMi}fTyD6%V^P%lPn({F(?uVh5XkdS|GK&;d@S>K6(z_% zD3@RRaA8G!1Y5~}wqmP_cVYYSI$Kq&!gf?1H9f&GQ$?Iu zkFzw?p=Nu_Ule}jBJz64+610+cPZDE^HD=i9j4$*lKYEO^6$iZCg$NR@nTh$Qx z(4u(w+L5A^L9XzR`ZTMd2|E_*(){qX@#6b0zIkJ6+cNZDFMWhsPxUQ}AG~;`I2~RV zn`HPfmqn8@UYuE27HxFF%0~;LzRwUdT?J7aHpHwbh`F~4_8EQZIL=Eqy@+)NxlHX_ zvg4jYES{S>)U6rvX~@0Gy~SIIm;d>akp1v~X335-Yc1Jv=dLb^smWzAJ+UlQ#O3{4 zCZ9JqPdsN%{;VM07%hmYVnIy*wjlCX3S#D5Vcl6c);sXu6T;rUSL~d-5u1B{`O>SF zXT%V#^0?IoRDc~oT#K7*Kij<`T4}sEw_`=jTwM|Q3oBv@b(ofy#a8o2<}7m0BX5s< z)|}gh*t-kj#I{$hdU^3L&OP{vB`X)KR^-)4<5r{m3TDyiBbhw!YH=6NGQ0b_s8`Ng zbJBI;@yATx0`41THh=EAxOD$%bLPr*@dxv7zbAjv^pPqyn=hCw=h!vyXX{L3k^DTz zy}~nLT=7mAm$+}-vn{ZnMO|iK@AioI@foF&=Ze0*G0gloOK)-C6(>LLH}^W{pI`MV zFPMJR-m`Gl%*yktIc0wJ`wR1{v@q`6cg&(1I%6dW5wMi7neRoig_JitKhd$}9 zvRX2rYr{GP;!!J`6VPm^qaFbp$#n5K9jZYAHBLrFAWE z_~^;@oF0um<#>wfdN$ENq-!}RzICj^^aA?T8ih1v=PeMr|v{&fUu*_ZVNs zx;l>@eB3%A<2<+qZXS_RLAG{Fwv)H}fb7^6V;$7f<_gI&N` z+P|!0{C0)fLi{`qyJ}z?hVKDUyNu1?hwb*e45(|j4Qsc?tUd?3=Xp^9*N&-MV^+P4 z=7b^m6xQ2;oP!_8wX62`=LVvGxK5y}T7p}HYIzNPP+rrpziKV>)e)GlvCpu!XQTc4 zB6-ot9c#u|IlRG1*dW>d`0a3ccg56;$y~pmCv^?HsKR=E^+fUhEo;VDdHF9%6?n-< zO%)Z>%aQ z^E<)w8~aDh0NWqgp#RneKCyv+W&{7y2L3nTx&GV&_Ww3`e#2d!a!({8{n4Bj=}!*_ zVwnu>iPD}pMIH|+wkkawNu&~bB(4oahmyLwzaoW2aBo)o&XAVVBZ4I|PeDLD$tlHae*N zr_&xiu6IVD(4&cDa9^Y+fpe$QaU>4!Uy2;T`JPOtpXz3J@uX^dy>q~f+zfoM!4UZ2clwCp3vgl<j3uz^6%zWVM*Cc5-?H>Fi(*!1>;3PCR`ob=SGLNcI*qH8PaB zTTgp14=wi+J<1dh=>*gJFe^-PX)a?k;c;@*oFhyva$`#sLq5lRAoVV8i literal 0 HcmV?d00001 diff --git a/obj/sgi_base_button.o b/obj/sgi_base_button.o new file mode 100644 index 0000000000000000000000000000000000000000..a635c463d94392aa7f6ab4049ed8daa610b64fa8 GIT binary patch literal 3012 zcma)8U1%It6h1SP*fd>r+HP%|#yXa&t0v=Yn%Y<&-1HYTEo(x-pNHvWchU~s?5?}B z{Q<$ygi_E-u|-4$_rV8S1S^&jN;LtCPmL6f4=TvcE*rGIC>D`YT)#6v%_Ju1ftz#B zIp6ucckkr2oqf9mL7;#HiqWh@^kI{0Y3_DejP9ifMYPlPe4_IgqJbLiFFR|9+9*+W zq-43K(Al~qmup1Hnncw4ccbwu?_)Gpmmv$uebq=}ta`K2Xxl+=*V%>?t?UzE`{+cy znXwwjDc2&}iF$tI^PhR|@ruiPxCZ2n(djxNH~V)Ze=Ipx=Y0bE?qCnz2buMK*hjE> z5K~4kvL8oQKC4UA?{Gci@;8pKwYMs0+p7Zl#7y4h{4#tZ^j7_*GVSEGi5YS7cr`); z&Lc!W{53i4M3mzdQQ1}%q1!-o{!eY%Nwkz5Q5l6U>D&+8E%=JsXhlS92|CR0yr>D7 z*YnPLcDfo*I5O~Z;!K@o z?la&)-9e6Pm_5f9lyWVqaJ(8h<$u}wmWn!j?^M7@6VumJ9x#vax zOuk0n>v0~z;u&1HaDL<@__>x(N3OZ@M`O*oy%o9_wH8WYP?6)lul(=|8t#jRa3hjRl3zJY8UlB z2@k_G1}zdgux;Mb*-Lk|F6nI%mWr)XL|D-j6;=tWr8UA@p-o&Ttrs^49RjJvW5c#F z2yPcVelXY-%#3QAM{QEmhHa2KSS*s-+rLMJjy>4!iB|e3#2mvoPF(FKHI*A4HnVWf z=4?~ly?0+{(Kb?tyaRBT>f|n*W>A2P0+{F zkivb8p^pS~+y~Df=;K-JId2yh)B7k?ad+My#_nkO@c*PzcmEzymj zabLk0rUDjBc~`(6#%&1%@Bp_Q`*4T{QBcr3!vh?1krh7O<|d)I2aMks?t?kcBpmNH z4yQTf7{mi?4u$ni^m`+0lwJgy%W(eF%u1{=qFd7j;xC%+Dv-%`E@jK2t(-_$_< z5i-B6f$To0gGSNR@zB`0teVQ_X`?|K)1<%DwTYiw&!Agb%huE8kWtFm$+$La0WiL) zV7^i^i?(hJ8wbo}$|7BN-&wtsJz{0kI>PGtg2q8N&$=Sse}&DMT$~s7FuQk$+=mLr zu(@zi`I21(eD8qWqXS_ZRwlk#@3T;2HkU@b2>X=22lXAy@xQOn zFZle5&(pX^?f1dXd^OR>%<*Hc_<9+4wtX$)f{S>QHJ@K)Jw84apGR>Q+uIQo^cZw5 Xt?<4jEc0)IIlmLk6`#j^uKD~QUK_Sa literal 0 HcmV?d00001 diff --git a/obj/sgi_base_check.o b/obj/sgi_base_check.o new file mode 100644 index 0000000000000000000000000000000000000000..7e337c04c96a63c5fe239637e0b6689bfbd9d5c0 GIT binary patch literal 2560 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 D&R*2i literal 0 HcmV?d00001 diff --git a/obj/sgi_base_grid.o b/obj/sgi_base_grid.o new file mode 100644 index 0000000000000000000000000000000000000000..aaea4be6957ca72e349891fc27f1e2a6acb219a4 GIT binary patch literal 3624 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 Ctvw9@ literal 0 HcmV?d00001 diff --git a/obj/sgi_base_indicator.o b/obj/sgi_base_indicator.o new file mode 100644 index 0000000000000000000000000000000000000000..cf6c41f09baa64bb5274e9872c25ffd375cbf9c8 GIT binary patch literal 1948 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 literal 0 HcmV?d00001 diff --git a/obj/sgi_base_picture.o b/obj/sgi_base_picture.o new file mode 100644 index 0000000000000000000000000000000000000000..812119ffab7585de3e72b8988df873b78e97f8a8 GIT binary patch literal 2348 zcma)7U2ofD6h4mIt}BI^QCQbT!$LvoU@=MQ*770Ivaw36o5D&ZKuE5WxSK^jjO}bg zLZVa^R}}4{_vB(1eB6|&s>(EI`2mqC5eY8ihExM?#w|jG=Qwui7PfJuH|IU)Jm}>O4Vbu*g%OMAyKY(5^@rY4aO1GJiO%BiXqR-0WJm%<0KDPt{-bY z=Sqp|4M8rurjK7A{?V1T&TkV<*E@&?`Vi+mxC}^JOWP)L*K1Xmq;mb%X4UOZEN!pO zR^7E!)s4||<94m$e!p39*Jms4tyIP3vsV*{%T<^2ILDSYcErSIH3|60=BG7F-q^7d z8#^CvZtT$JQk!odxVp{eZ@u7fH^eUre!^_o4LEWS0mmpf-UY|L#Ioo6v)Sxfq|Y0a zD%Y7yz@ZC0ubNd?l9smDz@Pi*3-ModEAHA4=)*)G=w;=NihC35e*N^`rynV`*!T&( z1oQA^_c!xXFjiK+n9o7;Y&dLxCC>N5SoykZ-n?9Nin66=E$ym;7)_o&{h~aSv5L0s z6pOj|g-JQ7B*&D59GA~tJQq(Y31#@WJfe&$!!&UU8Je!84H8aZ+c_Gapst<+6WzkW zNRQYn9Pa279v6;?{lZaUATlT(i##Qq5J<5<$U9mZ+Ob;ta$=G434)IkzrgXsf>`4DdzKf0m+4;qbrjaX5zM^W!`I5&>Y7y(j`Z? zxzYb8PXflzt;>h=w{(XczF>Ym8N}~Ff6wZ6H_b=s!nG4V?j2nUu&I|f@3BGV2e}M#_!F}*E2>N&(d(IukVmX6) zQfuq|GLGYK`& z7TVS>j`886mOF79!ubgNhp@O0?u(yE@Gh{Wkpo1Z1c$*6Z8_YQu)l-;Xto2`i2Jg{ zJtuIygPsT{{0k4VArbM0j)rW0V{HG@Cehw_C=nC37ta&7DGN7=L`9eGWF?ZCgJ6 z<9%_mFBxiDvvt)pGET|Tm5gapOruzq)OUtQIP6DMqhL5{R-e;KIVY7&hC+ZQpSSe) zOSCCWI_zD*|87?qqX?gvg z#P%L$>4mIr{WlmrO`n-kr%TqHmeGm#Gp4CqujUMgJ3MI=u4p*}7p$&Ydd5kOF^jpP zmA4^GtM$0}F9d)+2fg4C=E%NN%#y=15W|Y%1-`}lF`_DK40|`;SM&(cENcws4c74g d?E86^BmP)E6MVS%*m+*q=9ysK?`zrD{{WL51-<|P literal 0 HcmV?d00001 diff --git a/obj/sgi_base_radio.o b/obj/sgi_base_radio.o new file mode 100644 index 0000000000000000000000000000000000000000..8c9c45a529baf5b470d1cdf532b2467ffc8280cb GIT binary patch literal 2620 zcma)8Piz!r6o22&7M8M>DXvlr(FtO*Vmr>3A_XDNNXZ&dvfR zL<_7(lG60##XSn~P?ea*6j~GF$wo9A4|>_@WXeAi(GbFk^}U&$-DLyDmrURP-}m18 zzJ2MZdq(y$#=s{AQD|rYJweyg*6*??tb;HN4EElJ!IBl0ryPJ$dmTWx08RkZYjzZB{3((#JGmqK((cXr3CY9_qKn$tq3`}0V1yHg*UU9j9Mig;D_Hd(e(dkD# zI-?)uFn*N7OHtVI}`-8=@6&B7_NWWjLUcN7tt-(;q;y||Uq5mPq2c+{A(*Hz%Kw>rr zhpaH3bql_5>*9qOXFgW8m~`Hrk6pL;!D%OmeNxRn_iLD|<;<&Pi}C=D*a4g+8~f3o zSFc-tRjYT{;PmYdX{_>cY}VR<=K#))Fi2CX}qXz8e9$biQ9)!nh;$ytHIplb5Uz z=7*#U%d4;!jCbD|k3A6{;Se6>ci{bm<MeRL7B|oUR>@RB@tnqfXqM7@8eChHTMx|2i&4w zA2b8MkN0c2eaMLf#M|PD?q7-{>LeP*IQQXssvARbV9|ro+m7^FU zire9d?q46H6SZcDOQ_U)N1q=@ygoaWi`e8M8aq(t@uNP7(@dK2hVgRJJ_!1nMARD8 zY!AZU)rN=gn!ThqpFn!h-Aj#}*7&xD3ndO;Del!K^7LT6LFVGoKJcg&FVvDxFR(!z zuIy&w9(yTt{#xj+1tgKL$NmPJ5@?R2EqV%dilyyA@iQ&{FHxVu?+lho{-0a?}&1;Ig8O1~{2U}Fwk_6?$zCLogc16$Vrjpbq z)I!RXch>C~729TL9~HE`spx6-m?kH5P!xAZDuv7`J(E-rQ^^?;A@DkoPk^B8+DZVo8uH&s0q+pdi0SY0NY)Z9*YDhIH#{cL(3{lxKczeT(YV5DZJw;jNL&O$X_M7{|h Z;T&;V%1B#Lc4@u0Q%R@0Cyr1q{}%*fQ5*mO literal 0 HcmV?d00001 diff --git a/obj/sgi_base_updown.o b/obj/sgi_base_updown.o new file mode 100644 index 0000000000000000000000000000000000000000..08f36a300b70803d062a356d0821a9fcc02d38d6 GIT binary patch literal 3808 zcma)9e{36f6@Os(whCb=UHGRUbYFY!y6umYX^QqowD5U% zzSa#x<4NCp-}k=n`+2{<_dWYZ2f7bRl0+U!)IxV9qVNW1r8exa7LsWb-R@|8Cvfd> zku*c#ZO6`J=V9_o!bhDnuLW&;h}C-YftQT)qZ zexpXU-2Jlknj~8neDZ3i{p9tMZhaBkaS_*FrC;R;d<# zWp%vV4qrr8$>p}gJ>MPh$93d5yMfiAjXPM~;9q2_GvnZ+iixTyf(8Hgz&)a7%-wM!A%kQIpEBPgnR2OcpYD>aLeL|_X#7?3c zfqujORpJ@@_5Lxt4*Djd-+YjSZU4f}4fHM12%8TxOQJsctj%%*)+NO3Q>BuhzA0Ma zzg~LDiFJ#5wkRo9sZkj(e>!A|OUjgxl(Et!Wn46b7iX<@&PM<3 zKWbxkE#g3ZZ}^mRHpg1eF{y}&7H;}UM+S;5K)56-?j_fX+ zFZ41O0#|-tYLv&zlKO{IcGsfFg%-sO&cYFLYtJImEEG zLfDV>)yjTS25bix`j@{nW;4chW%+Ffmt5TJ)`G}kOz$j+nYM!9^T;uLfO|D#i9hFm zV$TDc^LYfgS8NxT@vj4W9`QEPL~%uSV@oRwHyK}&Q5WDgBgPBQow2XVFO@mAtGG+% zQKMPlun(>;$HcjEKAhV;aC5+&R@}Rcb56@RpX#LDfZF-;=j;^xr18$3&M(}g{Dkw4 zG$!#b^L_N} zn=+%xXyQ~{8A*($4W0#IU#%NW2I=$AMKK&Yw15BOO3Pp>kxrY5#BgiRA*C(Y)*e)q zR^?#tldWw*H5mGW5)SSShN$x~?1>nWffz}K-%GZ(EnNAE@`(!!SoMC%*X(^nR59tZ{&VIJT{pZx4@z5@Z-m1c41+OtZ zg2DEmWT(Q0_uw9K=zrmT6|1mIj#b&UxH?DUsx@P;9}RzY&~+jKQ_@dWI?0 zAlX3GMh}nIs;OFEL;qf@Ui06H*46s&@xcCS2)}!(NFsdi9lDCA@4xond+7Y=?2{FH zm$`EDokS!DpYIr#B**^Z9hmCqIiC7;czlxYk{?yN*I)ICWiVPZBI}5$WpsDTCj~qFuA56qe&7|fivD9nCqekjz&)4>Uqw9eF z#4w9d;w?v$Nh9^daLjb1gDJzPAd;>-9|wIjekvA^>WD#4rc?wGdX(dHL(^mNn5jpN zp~&bkLQ?Opz_9JnlyPFzNSk_WB=VG@4aQg*@{~gyqN5A#xw{WwpM*JVaBW=7lNCr; z=RmS56s|%XN<~JDj}J0AYNlb{(`UBpurMRB;kG?`cMLJd6H&wI!an^lif}BEIDUYk zqr;lxp*rT2Q{Rtuac`fT)~1uGSlk?HdyHe>6N{gW49D;#H1rhrubm?wN~A{8AmA&|l%h%pW3Z#Mx`Y2e6B|Le$NC zC(*Tvp6>_WCZd)Kp8{upd>JzTfcfWem*bvjYDPTZKE5zPUj&9j_q*RYmiawm&UY7c HrNaLM@9$N7 literal 0 HcmV?d00001 diff --git a/obj/sgi_base_window.o b/obj/sgi_base_window.o new file mode 100644 index 0000000000000000000000000000000000000000..240be48dd6e0750bf1ed59fdc8f6cbd8648f1ce6 GIT binary patch literal 2444 zcma)8OKcle6ulEWshhfBQWruRl@T&hfO;4^DX9R7gqB8vwz8U32!u2q+mm*Lf6Pq! zk&sBMcGo}_&58vUVu28gsEXRCqKSoAltrXSWWz2KYoby%WyJ=SyTk(!;LStm@?$GM1O$yc2yMr``- z{a~&a_z!n|t#PpViXB4?L9E$Tj)NGB>7VVGyWivJlltQDbA0T3Ukv+RMXbg3HJh*> zcj{|)M4s7L$gbJ9GHb|x!}%WlFQNZM^nNGf^}is)FRt0Vj@Ov6<;{@%*?J88j{5a= zLtNf8<>k#!>dTu{pYi%c{c+T4`@PP8Crl?$#Qgj>(^+Wz(K*K7hNknyN?8-lDPvO2 zYvQD;7bT*xqeov82l7V6G_6Xdm^?KmrliynNfwjh@zd`nQ<5yDUlfO=VJS_cuOghP zsX3j5LohpslcUtty=ycg?C$6eMTMSlT-Yx>6Y3S775X|3gbsE*FB}p`GB1@ZH3w}O zo<0{?hE|j;?V?3eLA6wpa;8br=;@OZ=6D7BJ*XEh0#=yDaZ=I{N%=~tq?NI_T(LB1 z?9`d0X{q^-ya=jg8G3HY(oFZl{I8Gaz~VjY^4WaXqB!h<;JbDO_kec$Hmfi|7J4rR zuV-Ea;{_jkSC?p{Ef!oZmo@I8%l|K)?5_#JJSyIs9}i5TW=s3E>-KeoMOCc>ErCvSqk1 zgcG-&&nLDeA?j`cSfOnvh4CKZd%(gudQk5%54xYck9-~iVSFh7(2Qqx;4gOI+75gh zm~*`W&G|NV_`BiDVsIzyAA-&A-`74a!48D;lX+HGa;m8*7xZ$WazV;htCUbFQ6S}m z^dNgZhoYBtODSlR>QvFnq~w+d#MGdneLSU^mZF!`vsxyvyOZvNtN0IYCY2gLc0w8V zo?m}aQRCF!qVvT5Gu5hQyj9dKs!mxZDT@2tDpO@HLqT;))sVTi!>tNX*5j&6r|^in zi5_22dZ;brq@k9yNAFP~S7Iv#ONF|@puIl?(7D@MtL5b=MN zeq3fgNBuqc6~THR(RF|R9&0>2tNwf(-)BEAjR@Vb2j_w@_!-tX-1k_6|0iqzu)Y*L S0Qlj;=Y%nz1=f5YSpN-ykqKM? literal 0 HcmV?d00001 diff --git a/obj/sgi_data.o b/obj/sgi_data.o new file mode 100644 index 0000000000000000000000000000000000000000..6ef277f7df80637f6486fb7adc5366f8fccea9ac GIT binary patch literal 23684 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 Op3nRp3f|cz#Qz6H;TL`Y literal 0 HcmV?d00001 diff --git a/obj/sgi_form_manage.o b/obj/sgi_form_manage.o new file mode 100644 index 0000000000000000000000000000000000000000..238d41e8f1d750b638cdf602e9351fe351027251 GIT binary patch literal 13036 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 HPJn*^5QOWB literal 0 HcmV?d00001 diff --git a/obj/sgi_log.o b/obj/sgi_log.o new file mode 100644 index 0000000000000000000000000000000000000000..1336d8ec75750e1af1f9d8095d30cedfe103202a GIT binary patch literal 13108 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 BCuRTu literal 0 HcmV?d00001 diff --git a/obj/sgi_resource.o b/obj/sgi_resource.o new file mode 100644 index 0000000000000000000000000000000000000000..6b573e7294c1603e60a26e10b596db22c6ad33d9 GIT binary patch literal 10028 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 Ik8Tv=mrulvU;qFB literal 0 HcmV?d00001 diff --git a/obj/sgi_string.o b/obj/sgi_string.o new file mode 100644 index 0000000000000000000000000000000000000000..2ebdd72b5e0813b370f2d0869c0cdcaf42d76580 GIT binary patch literal 2480 zcma)8U1%It6h1RMZPIO8))-Nfv<^}s#qM|$LsP|v-PERtO=;2yiUHkh*0`8tLuO)H z2$(iL8YwNFGBmUGt(_G3N}=*YH-%|e6pVy(Pr6Y+0mfv-l*t^O{cS-CYJn%kysM6y21J-vF4S`b!i)U zw8x>(^3A}@;=X)Gx#DG$Z4L*&u??yOtXqa&j6U-?M`erS;W$g~y4MChj)P$fY$jln zZD?jcYD(?!{cst)n3>-sL)S+)vyBNT4-AnTQWD*1J>nyrSGu*sMV(7UaKy+hynHI z{G&bK`ZZ$ym);rf$9JQ8+&iVm@#^Mcg=dF*g*Y_s`GSks-ER^5Xu$F^H}gV;T$US> za++9|xs}Du%I~2J_k{DbxoxGB@^=QVx??el5?b+Y5k(PNU$HrENqq%ckn(G?2`Rw|JVU> z9C`Lj`P ztv;)V(nm3WnOtTpPudZnyZVx8+8u97H*0(Jc&tThHQKZ%v?pUvX-{kIdPnS_{;YOH zBg;NNE`3=O-s-w^jJnT`AfR{j+;T!9-9QsDj;WCXr z%G0Y1gf#Q`Jdexr|0O3N!#WK4usy4e%3tR3eJOl{YphXCMH~1#7CljGtgpJR)!%YhwE_% z_bc#KepST;Wd6^O&}2{K-@(r3rzfl|9m>?{8PLvq-ACy|d%lj#_sQHe-dH0$6C%?M zEIYOH)ZYAQJ_1r87K5UJD!^i(Y!sLpU5*K uZ_i6qI-7F}lQfl^vU3j2XYnbWtnYFs7KH0~03Vh$z|I5sKaAl)qQ3z`8F{(@ literal 0 HcmV?d00001 diff --git a/obj/uart.o b/obj/uart.o new file mode 100644 index 0000000000000000000000000000000000000000..20ed053ed3d2352563b8319810f65527012bb02e GIT binary patch literal 2924 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 literal 0 HcmV?d00001 diff --git a/src/crc.cpp b/src/crc.cpp new file mode 100644 index 0000000..c153f5a --- /dev/null +++ b/src/crc.cpp @@ -0,0 +1,49 @@ +#include "sgi_types.h" + +static const u32 crc32_table[256] = +{ + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D, +}; + +u32 crc32_calc(u8 *src, s32 bytes) +{ + u32 crc32 = 0xffffffff; + + while (bytes-- > 0) { + crc32 = (crc32 >> 8) ^ crc32_table[(crc32 & 0xff) ^ *src++]; + } + + return (~crc32); + +}//end of crc32_calc() diff --git a/src/finger_intf.cpp b/src/finger_intf.cpp new file mode 100644 index 0000000..742f472 --- /dev/null +++ b/src/finger_intf.cpp @@ -0,0 +1,402 @@ +#include +#include +#include "global_func.h" + +static volatile s32 s_cancel_flag; /* user cancel operate */ +static volatile s32 s_busy_flag; /* module busy */ +static volatile u32 s_result; /* module result */ +static volatile s32 s_error_flag; /* module error */ +static volatile s32 s_ops; /* module operate type */ + +pthread_t g_fpr_thread; + +s32 fpr_get_cancel_flag(void) +{ + return __sync_fetch_and_or(&s_cancel_flag, 0); +} + +void fpr_set_cancel_flag(void) +{ + __sync_lock_test_and_set(&s_cancel_flag, 1); +} + +static inline void fpr_reset_cancel_flag(void) +{ + __sync_lock_release(&s_cancel_flag); +} + +s32 fpr_get_busy_flag(void) +{ + return __sync_fetch_and_or(&s_busy_flag, 0); +} + +static inline void fpr_set_busy_flag(void) +{ + __sync_lock_test_and_set(&s_busy_flag, 1); +} + +static inline void fpr_reset_busy_flag(void) +{ + __sync_lock_release(&s_busy_flag); +} + +u32 fpr_get_result(void) +{ + return __sync_fetch_and_or(&s_result, 0); +} + +static inline void fpr_set_result(u32 result) +{ + __sync_lock_test_and_set(&s_result, result); +} + +static inline void fpr_reset_result(void) +{ + __sync_lock_release(&s_result); +} + +s32 fpr_get_error_flag(void) +{ + return __sync_fetch_and_or(&s_error_flag, 0); +} + +static void fpr_set_error_flag(void) +{ + __sync_lock_test_and_set(&s_error_flag, 1); +} + +static inline void fpr_reset_error_flag(void) +{ + __sync_lock_release(&s_error_flag); +} + +static inline s32 fpr_get_ops(void) +{ + return __sync_fetch_and_or(&s_ops, 0); +} + +static inline void fpr_set_ops(s32 ops) +{ + __sync_lock_test_and_set(&s_ops, ops); +} + +static inline void fpr_reset_ops(void) +{ + __sync_lock_release(&s_ops); +} + +static void finger_enroll_1(void) +{ + s32 r; + s32 id; + u32 uid; + + /* 清除cancel标志,置错误标志 */ + fpr_reset_cancel_flag(); + fpr_set_error_flag(); + + /* 寻找空的指纹存储位置 */ + id = fpr_find_free_area(); + if (id == COMM_ERR) { + goto err; + } + + /* 发送开始登记指令 */ + uid = id | (0 << 16); + if (fpr_enroll_start(uid) != 0) { + goto err; + } + + /* 捕捉指纹并进行第一次登记 */ + r = fpr_capture_finger(TIMEOUT_IDENT); + if (r == 0) { + if (fpr_enroll_1() == 0) { + /* 更新返回结果,置成功标志 */ + fpr_set_result(uid); + fpr_reset_error_flag(); + + printf("Enroll 1 ok, id: %d\n", uid); + + } + else { + printf("fpr enroll fail.\n"); + } + } + else if (r == CANCEL_ERR) { /* 用户取消操作 */ + fpr_capture_cancel(); + printf("fpt user cancel operate.\n"); + } + else { + printf("fpr capture finger fail: 0x%x\n", r); + close_comm(); + SDL_Delay(1000); + open_comm(); + SDL_Delay(1000); + } + +err: + /* 清除busy标志 */ + fpr_reset_busy_flag(); +} + +static void finger_enroll_2(void) +{ + s32 r; + + /* 清除cancel标志,置错误标志 */ + fpr_reset_cancel_flag(); + fpr_set_error_flag(); + + /* 捕捉指纹并进行第二次登记 */ + r = fpr_capture_finger(TIMEOUT_IDENT); + if (r == 0) { + if (fpr_enroll_2() == 0) { + /* 更新返回结果,置成功标志 */ + //fpr_set_result(uid); + fpr_reset_error_flag(); + + printf("Enroll 2 ok\n"); + + } + else { + printf("fpr enroll fail.\n"); + } + } + else if (r == CANCEL_ERR) { /* 用户取消操作 */ + fpr_capture_cancel(); + printf("fpt user cancel operate.\n"); + } + else { + printf("fpr capture finger fail: 0x%x\n", r); + close_comm(); + SDL_Delay(1000); + open_comm(); + SDL_Delay(1000); + } + + /* 清除busy标志 */ + fpr_reset_busy_flag(); +} + +static void finger_enroll_3(void) +{ + s32 r; + + /* 清除cancel标志,置错误标志 */ + fpr_reset_cancel_flag(); + fpr_set_error_flag(); + + /* 捕捉指纹并进行第三次登记 */ + r = fpr_capture_finger(TIMEOUT_IDENT); + if (r == 0) { + if (fpr_enroll_3() == 0) { + /* 更新返回结果,置成功标志 */ + //fpr_set_result(uid); + fpr_reset_error_flag(); + + printf("Enroll 3 ok\n"); + + } + else { + printf("fpr enroll fail.\n"); + } + } + else if (r == CANCEL_ERR) { /* 用户取消操作 */ + fpr_capture_cancel(); + printf("fpt user cancel operate.\n"); + } + else { + printf("fpr capture finger fail: 0x%x\n", r); + close_comm(); + SDL_Delay(1000); + open_comm(); + SDL_Delay(1000); + } + + /* 清除busy标志 */ + fpr_reset_busy_flag(); +} + +static void finger_identify(void) +{ + s32 r; + u32 uid = 0; + + // test + printf("start finger identify.\n"); + + /* 清除cancel标志,置错误标志 */ + fpr_reset_cancel_flag(); + fpr_set_error_flag(); + + /* 捕捉指纹并进行比对,返回结果 */ + r = fpr_capture_finger(TIMEOUT_IDENT); + if (r == 0) { + if (fpr_identify(&uid) == 0) { + /* 更新返回结果,置成功标志 */ + fpr_set_result(uid); + fpr_reset_error_flag(); + + printf("Found match finger, id: %d\n", uid); + + } + else { + printf("fpr identify fail.\n"); + } + } + else if (r == CANCEL_ERR) { /* 用户取消操作 */ + fpr_capture_cancel(); + printf("fpt user cancel operate.\n"); + } + else { + printf("fpr capture finger fail: 0x%x\n", r); + close_comm(); + SDL_Delay(1000); + open_comm(); + SDL_Delay(1000); + } + + /* 清除busy标志 */ + fpr_reset_busy_flag(); + +} + +static s32 module_signal_handle(void) +{ + s32 ops; + + /* 获取操作类型 */ + ops = fpr_get_ops(); + printf("ops: %d\n", ops); + switch(ops) { + case FPR_IDENTIFY: + finger_identify(); + break; + + case FPR_ENROLL_1: + finger_enroll_1(); + break; + + case FPR_ENROLL_2: + finger_enroll_2(); + break; + + case FPR_ENROLL_3: + finger_enroll_3(); + break; + + case FPR_QUIT: + return FPR_QUIT; + + default: + break; + } + + return 0; +} + +static void *comm_thread(void *arg) +{ + int s,sig; + sigset_t set; + + /* 初始指纹模块 */ + if (fpr_init() != 0) { + printf("fpr init fail.\n"); + return NULL; + } + printf("fpr init ok.\n"); + +#if 1 + if (fpr_open() != 0) { + printf("fpr open fail.\n"); + return NULL; + } + printf("fpr open ok.\n"); +#endif + + // test + printf("thread start().\n"); + + /* 等待堵塞的信号 */ + sigemptyset(&set); + sigaddset(&set, FPR_SIGNAL); + + /* 通讯循环,等待信号触发 */ + for (;;) { + s = sigwait(&set, &sig); + if (s != 0) { + printf("sigwait error: %d\n", s); + } + + if (sig == FPR_SIGNAL) { + s = module_signal_handle(); + if (s == FPR_QUIT) { + printf("thread is quit.\n"); + break; + } + } + else { + printf("sigwait(): %d.\n", sig); + } + } + + printf("thread end().\n"); + + return NULL; +} + +s32 fpr_module_init(void) +{ + int s; +#if 0 + /* 初始指纹模块 */ + if (fpr_init() != 0) { + printf("fpr init fail.\n"); + return FAIL; + } + + if (fpr_open() != 0) { + printf("fpr open fail.\n"); + return FAIL; + } +#endif + + /* 初始化线程属性,均设为默认值,创建线程并开始通讯 */ + pthread_attr_t attr; + sched_param param; + pthread_attr_init(&attr); + pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); + pthread_attr_getschedparam(&attr, ¶m); + param.sched_priority = 20; + pthread_attr_getschedparam(&attr, ¶m); + s = pthread_create(&g_fpr_thread, &attr, &comm_thread, NULL); + if (s != 0) { + printf("pthread_create error: %d\n", s); + return FAIL; + } + + return 0; +} + +void fpr_module_deinit(void) +{ + /* 关闭指纹模块 */ + fpr_close(); + fpr_deinit(); + + /* 退出模块线程 */ + fpr_module_trigger(FPR_QUIT); + + /* 等待模块线程退出 */ + pthread_join(g_fpr_thread, NULL); +} + +void fpr_module_trigger(s32 ops) +{ + /* 置忙标志 */ + fpr_set_busy_flag(); + + fpr_set_ops(ops); + pthread_kill(g_fpr_thread, FPR_SIGNAL); +} diff --git a/src/fingerprint.cpp b/src/fingerprint.cpp new file mode 100755 index 0000000..f5fcf07 --- /dev/null +++ b/src/fingerprint.cpp @@ -0,0 +1,303 @@ +#include +#include +#include +#include "fingerprint.h" +#include "global_def.h" +#include "global_func.h" + +static u8 s_receive_buffer[128 * 1024] = {0}; +static u32 s_user[2000]; + +static u16 s_devid = 0x0001; + +static u16 checksum(u8 *data, int size) +{ + u16 cks = 0; + + for (; size > 0; size--) { + cks += *data++; + } + + return cks; +} + +static void encode_cmd(struct command_packet *packet, u32 param, u16 cmd) +{ + /* fill data */ + packet->prefix = IPREFIX; + packet->devid = s_devid; + packet->param = param; + packet->cmd = cmd; + + /* calc checksum */ + packet->checksum = checksum((u8 *)packet, + sizeof(struct command_packet) - sizeof(packet->checksum)); +} + +static int decode_cmd(struct command_packet *packet, u32 *response) +{ + u32 r; + + if (packet->cmd == ACK) { + if (response != NULL) { + *response = packet->param; + } + r = 0; + } + else { + r = packet->param | MODULE_ERR; + } + + return r; +} + +static int transfer_cmd(u16 cmd, u32 in_param, u32 *out_param, u32 timeout) +{ + s32 r; + u16 cks; + struct command_packet tx; + struct command_packet rx; + + /* 准备发送数据 */ + encode_cmd(&tx, in_param, cmd); + + /* 发送并接收数据 */ + if ((r = transfer((u8 *)&tx, sizeof(tx), (u8 *)&rx, sizeof(rx), + timeout)) == 0) { +#if 0 + // test + int i; + u8 *p = (u8 *)℞ + printf("rx: "); + for (i = 0; i < sizeof(rx); ++i) { + printf("0x%02X, ", *p++); + } + printf("\n"); +#endif + do { + if (rx.prefix != IPREFIX) { + break; + } + + cks = checksum((u8 *)&rx, sizeof(rx) - sizeof(rx.checksum)); + if (cks != rx.checksum) { + break; + } + + r = decode_cmd(&rx, out_param); + } while (0); + } + + return r; +} + +static int transfer_data(u16 cmd, u32 in_param, u32 *out_param, u8 *data) +{ + return 0; +} + +static int receive_data(u8 *buffer, u32 len, u32 timeout) +{ + u16 cks; + u32 rx_len; + u32 r = COMM_ERR; + + rx_len = len + 6; + memset(s_receive_buffer, 0, sizeof(s_receive_buffer)); + if (uart_receive(s_receive_buffer, rx_len, timeout) == 0) { + do { + if (*(u16 *)s_receive_buffer != DPREFIX) { + break; + } + + cks = checksum(s_receive_buffer, rx_len - sizeof(cks)); + if (cks != *(u16 *)(s_receive_buffer + rx_len - sizeof(cks))) { + break; + } + + /* output data */ + memcpy(buffer, s_receive_buffer + PARAM_LL_OF, len); + + /* set success flag */ + r = 0; + } while (0); + } + + return r; +} + +int fpr_init(void) +{ + return open_comm(); +} + +void fpr_deinit(void) +{ + close_comm(); +} + +int fpr_open(void) +{ + return transfer_cmd(CMD_OPEN, 0, NULL, TIMEOUT_N); +} + +int fpr_close(void) +{ + return transfer_cmd(CMD_CLOSE, 0, NULL, TIMEOUT_N); +} + +int fpr_get_ver(u32 *ver) +{ + return transfer_cmd(CMD_VER, 0, ver, TIMEOUT_N); +} + +int fpr_get_security_level(u32 *level) +{ + return transfer_cmd(CMD_LEVEL, 0, level, TIMEOUT_N); +} + +int fpr_set_security_level(u32 level) +{ + return transfer_cmd(CMD_LEVEL, level, NULL, TIMEOUT_N); +} + +int fpr_set_baudrate(u32 baudrate) +{ + return transfer_cmd(CMD_BAUDRATE, baudrate, NULL, TIMEOUT_N); +} + +int fpr_get_devid(u32 *devid) +{ + if (transfer_cmd(CMD_GET_DEVID, 0, devid, TIMEOUT_N) == 0) { + s_devid = *devid; + return 0; + } + + return COMM_ERR; +} + +int fpr_set_devid(u32 devid) +{ + return transfer_cmd(CMD_SET_DEVID, devid, NULL, TIMEOUT_N); +} + +int fpr_get_enroll_count(u32 *count) +{ + return transfer_cmd(CMD_GET_ENROLL_COUNT, 0, count, TIMEOUT_N); +} + +int fpr_check_enrolled(u32 *enrolled) +{ + return transfer_cmd(CMD_CHECK_ENROLLED, 0, enrolled, TIMEOUT_N); +} + +int fpr_enroll_start(u32 uid) +{ + return transfer_cmd(CMD_ENROLL_START, uid, NULL, TIMEOUT_N); +} + +int fpr_enroll_1(void) +{ + return transfer_cmd(CMD_ENROLL_1, 1, NULL, TIMEOUT_E); +} + +int fpr_enroll_2(void) +{ + return transfer_cmd(CMD_ENROLL_2, 2, NULL, TIMEOUT_E); +} + +int fpr_enroll_3(void) +{ + return transfer_cmd(CMD_ENROLL_3, 3, NULL, TIMEOUT_E); +} + +int fpr_check_press_finger(u32 *state) +{ + return transfer_cmd(CMD_PRESS_FINGER, 0, state, TIMEOUT_N); +} + +int fpr_get_all_user(u32 *count, u32 *list) +{ + u32 r; + + *count = 0; + r = transfer_cmd(CMD_GET_ALL_USER, 0, count, TIMEOUT_N); + if (r == 0) { + return receive_data((u8 *)list, *count * 4, TIMEOUT_U); + } + else if ((r & 0xffff) == 0x100A) { /* database empty */ + return 0; + } + + return COMM_ERR; +} + +int fpr_set_user_priv(u32 new_priv, u32 *old_priv) +{ + return transfer_cmd(CMD_SET_USER_PRIV, new_priv, old_priv, TIMEOUT_N); +} + +int fpr_delete_user(u32 uid) +{ + return transfer_cmd(CMD_DEL_ID, uid, NULL, TIMEOUT_N); +} + +int fpr_delete_all(void) +{ + return transfer_cmd(CMD_DEL_ALL, 0, NULL, TIMEOUT_N); +} + +int fpr_verify(u32 uid) +{ + return transfer_cmd(CMD_VERIFY, uid, NULL, TIMEOUT_N); +} + +int fpr_identify(u32 *match_id) +{ + return transfer_cmd(CMD_IDENTIFY, 0, match_id, TIMEOUT_I); +} + +int fpr_capture_finger(u32 timeout) +{ + return transfer_cmd(CMD_CAPTURE_FINGER, timeout, NULL, (timeout + 2) * 1000); +} + +int fpr_capture_cancel(void) +{ + return transfer_cmd(CMD_CAPTURE_CANCEL, 0, NULL, TIMEOUT_N); +} + +int fpr_get_image(u8 *image) +{ + if (transfer_cmd(CMD_UP_IMAGE, 0, NULL, TIMEOUT_N) == 0) { + return receive_data(image, 256 * 256, TIMEOUT_D); + } + + return COMM_ERR; +} + +int fpr_find_free_area(void) +{ + u32 count; + u32 i,j; + int find; + + if (fpr_get_all_user(&count, s_user) == 0) { + for (i = RESERVED_CAP; i < MODULE_CAP; ++i) { + find = 0; + for (j = 0; j < count; ++j) { + if (i == (s_user[j] & 0xffff)) { + find = 1; + break; + } + } + + /* ID is exist ? */ + if (!find) { + return i; + } + } + } + + return COMM_ERR; +} diff --git a/src/fingerprint.h b/src/fingerprint.h new file mode 100755 index 0000000..3f735e4 --- /dev/null +++ b/src/fingerprint.h @@ -0,0 +1,107 @@ +#ifndef FINGERPRINT_H +#define FINGERPRINT_H + +#include "sgi_types.h" + +/* Common define */ +#define IPR0 0x55 /* 指令前缀 1 */ +#define IPR1 0xAA /* 指令前缀 2 */ +#define IPREFIX 0xAA55 +#define DPREFIX 0xA55A + +#define RPR0 0x55 /* 应答前缀 1 */ +#define RPR1 0xAA /* 应答前缀 2 */ +#define ACK 0x30 /* 正常响应 */ +#define NACK 0x31 /* 非正常响应 */ + +#define NTX_SIZE 12 +#define NRX_SIZE 12 +#define CHKSUM_SIZE 2 +#define PARAM_SIZE 4 +#define CMD_SIZE 2 + +#define MODULE_CAP 2000 +#define RESERVED_CAP 5 + +#define TIMEOUT_N 1000 +#define TIMEOUT_E 2000 +#define TIMEOUT_U 3000 +#define TIMEOUT_I 15000 +#define TIMEOUT_D 15000 + +#define TEMPLATE_SIZE 1404 +#define IMAGE_SIZE 65536 + +#define COMM_ERR -1 +#define MODULE_ERR 0x80000000 + +#define PR0_OF 0 +#define PR1_OF 1 +#define DEVID_LL_OF 2 +#define DEVID_LH_OF 3 +#define PARAM_LL_OF 4 +#define PARAM_LH_OF 5 +#define PARAM_HL_OF 6 +#define PARAM_HH_OF 7 +#define CMD_LL_OF 8 +#define CMD_LH_OF 9 +#define RESP_LL_OF 8 +#define RESP_LH_OF 9 + +/* Command define */ +#define CMD_OPEN 0x01 /* 初始化模块 */ +#define CMD_CLOSE 0x02 /* 终止模块使用 */ +#define CMD_VER 0x04 /* 读取模块版本 */ +#define CMD_SLEEP 0x05 /* 使用模块进入休眠状态 */ +#define CMD_LEVEL 0x06 /* 设置/读取比对等级 */ +#define CMD_BAUDRATE 0x11 /* 设置波特率 */ +#define CMD_GET_DEVID 0x12 /* 读取模块序列号 */ +#define CMD_SET_DEVID 0x13 /* 设置模块序列号 */ +#define CMD_GET_ENROLL_COUNT 0x20 /* 读取用户总数 */ +#define CMD_CHECK_ENROLLED 0x21 /* 检查指定ID是否占用 */ +#define CMD_ENROLL_START 0x22 /* 启动指纹登记 */ +#define CMD_ENROLL_1 0x23 /* 指纹登记第一次模板生成 */ +#define CMD_ENROLL_2 0x24 /* 指纹登记第二次模板生成 */ +#define CMD_ENROLL_3 0x25 /* 指纹登记第三次模板生成 */ +#define CMD_PRESS_FINGER 0x26 /* 检查手指是否放在指纹采集仓上 */ +#define CMD_GET_ALL_USER 0x32 /* 获取已登录的所有用户ID */ +#define CMD_SET_USER_PRIV 0x33 /* 设置读取用户权限 */ +#define CMD_DEL_ID 0x40 /* 删除指定ID用户 */ +#define CMD_DEL_ALL 0x41 /* 删除所有用户 */ +#define CMD_VERIFY 0x50 /* 已获取的指纹图像与指定ID的指纹模板进行1:1比对 */ +#define CMD_IDENTIFY 0x51 /* 已获取的指纹图像与所有指纹模板进行1:N比对 */ +#define CMD_VERIFY_TEMPLATE 0x52 /* 下载指纹模板与指定ID的指纹模板进行1:1比对 */ +#define CMD_IDENTIFY_TEMPLATE 0x53 /* 下载指纹o模板与所有指纹模板进行1:N比对 */ +#define CMD_CAPTURE_FINGER 0x60 /* 采集指纹图像 */ +#define CMD_CAPTURE_CANCEL 0x61 /* 取消指纹采集 */ +#define CMD_UP_IMAGE 0x62 /* 上传指纹图像到主机 */ +#define CMD_EXTRACT_TEMPLATE 0x65 /* 从指纹图像中提取指纹模板并上传到主机 */ +#define CMD_UP_TEMPLATE 0x70 /* 上传指定ID的指纹模板到主机 */ +#define CMD_DOWN_TEMPLATE 0x71 /* 下载指纹模板到指定ID号 */ +#define CMD_AUTO_ADJUST 0x80 /* 自动调整图像传感器参数 */ +#define CMD_DUPLICATION_CHECK 0x81 /* 设置/读取指纹注册时的重复检查 */ +#define CMD_SET_LED 0x82 /* 打开/关闭指纹模块LED */ + +struct command_packet { + u16 prefix; + u16 devid; + u32 param; + u16 cmd; + u16 checksum; +}__attribute__((packed)); + +struct template_packet { + u16 prefix; + u16 devid; + u8 data[TEMPLATE_SIZE]; + u16 checksum; +}__attribute__((packed)); + +struct image_packet { + u16 prefix; + u16 devid; + u8 data[IMAGE_SIZE]; + u16 checksum; +}__attribute__((packed)); + +#endif \ No newline at end of file diff --git a/src/fm_alarm.cpp b/src/fm_alarm.cpp new file mode 100644 index 0000000..0a78163 --- /dev/null +++ b/src/fm_alarm.cpp @@ -0,0 +1,144 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_alarm + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_alarm; /* */ +static union sgi_object s_btn_cancel; /* */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static s32 s_alarm_flash = 0; + +static struct sgi_widget s_widget[3] = { + {125, 118, 545, 172, {"alarm.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_alarm_flash = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_cancel_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_alarm_pwd)); +} + +static void btn_back_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + static u32 cycle = 0; + s32 flash = 0; + u16 *info; + + /* per 6s update dispaly */ + if (TIME_AFTER(SDL_GetTicks(), cycle)) { + info = get_current_alarm_info(&flash); + if (info) { + set_object_text_u(&s_lbl_alarm.label, info); + } + else { + set_object_text_w(&s_lbl_alarm.label, L"枪弹柜异常报警!"); + } + s_lbl_alarm.label.redraw = 1; + + if (!s_alarm_flash && flash) { + alarm_ctrl(ALARM_ON); + } + cycle = SDL_GetTicks() + 4000; + } + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* */ + LABEL_CREATE(s_lbl_alarm, FORM_CLASS(MODULE_NAME), 142, 174, 516, 60, 1, + "jht.ttf", 26, color); + s_lbl_alarm.label.align = DT_CENTER; + + /* */ + BUTTON_CREATE(s_btn_cancel, FORM_CLASS(MODULE_NAME), 346, 318, 107, 44, 1, + "btn-free-u.png", "btn-free-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_cancel.button.up = btn_cancel_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_alarm_pwd.cpp b/src/fm_alarm_pwd.cpp new file mode 100644 index 0000000..0f818e9 --- /dev/null +++ b/src/fm_alarm_pwd.cpp @@ -0,0 +1,188 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_alarm_pwd + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[3] = { + {165, 59, 377, 95, {"pwd-2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_alarm)); +} + +static void btn_main_up(struct sgi_button *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; + sgi_form_show(&FORM_CLASS(fm_alarm)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_manager_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + /* 取消警报 */ + cancel_alarm(); + sgi_form_show(&FORM_CLASS(fm_main)); + + /* log */ + record_manager_log(g_passport.mname, L"解除系统警报"); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 86, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 126, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_main_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_card_manager.cpp b/src/fm_borrow_card_manager.cpp new file mode 100644 index 0000000..a5abed8 --- /dev/null +++ b/src/fm_borrow_card_manager.cpp @@ -0,0 +1,194 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_card_manager + +FORM_MODULE(MODULE_NAME); /* 取枪模块,管理员刷卡验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_card_start = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[3] = { + {333, 88, 273, 234, {"card.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; + s_card_start = 0; + card_start(); +} + +static void form_exit(struct sgi_form *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_user)); +} + +static void btn_card_up(struct sgi_button *) +{ + +} + +static void btn_pwd_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_borrow_pwd_user)); +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + s32 card; + + do { + r = card_state(); + if (r == -1) { + card_start(); + } + else if (r == 1) { + card = get_card_id(); + r = search_mid(&g_passport, SR_CARD, card); + if (r == 0) { + g_passport.visit &= MGR_CARD_MASK; + g_passport.visit |= MGR_CARD_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_photo_user)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"卡号无对应的用户信息!", + 0, NULL); + card_start(); + } + } + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 600, 50, 200, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.state |= 2; + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_card_user.cpp b/src/fm_borrow_card_user.cpp new file mode 100644 index 0000000..1b7cc3d --- /dev/null +++ b/src/fm_borrow_card_user.cpp @@ -0,0 +1,202 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_card_user + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员刷卡验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_card_start = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {333, 88, 273, 234, {"card.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; + s_card_start = 0; + card_start(); +} + +static void form_exit(struct sgi_form *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_user)); +} + +static void btn_card_up(struct sgi_button *) +{ + +} + +static void btn_pwd_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_borrow_pwd_user)); +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + s32 card; + + do { + //if (!s_card_start) { + // break; + //} + r = card_state(); + if (r == -1) { + card_start(); + } + else if (r == 1) { + card = get_card_id(); + r = search_uid(&g_passport, SR_CARD, card); + if (r == 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_CARD_MASK; + g_passport.visit |= USR_CARD_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"卡号无对应的用户信息!", + 0, NULL); + card_start(); + } + } + + //s_card_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.state |= 2; + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_fpr_manager.cpp b/src/fm_borrow_fpr_manager.cpp new file mode 100644 index 0000000..f60102f --- /dev/null +++ b/src/fm_borrow_fpr_manager.cpp @@ -0,0 +1,266 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_fpr_manager + +FORM_MODULE(MODULE_NAME); /* 取枪模块,管理员指纹验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {323, 90, 272, 234, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static void form_exit(struct sgi_form *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ +// if (s_fpr_start && fpr_get_busy_flag()) { +// fpr_set_cancel_flag(); +// } +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// s_timer = 60; +// } +} + +static void btn_card_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_borrow_card_manager)); +} + +static void btn_pwd_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_borrow_pwd_manager)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + s_fpr_fail = 0; + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { +// if (!s_fpr_start) { +// break; +// } + + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + play_effect_fpr(); + fpr_module_trigger(FPR_IDENTIFY); + s_fpr_start = 1; + printf("start identify.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无效,请重新采集!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + r = search_mid(&g_passport, SR_FPR, r); + printf("fpr result: %d\n", r); + if (r == 0) { + g_passport.visit &= MGR_FPR_MASK; + g_passport.visit |= MGR_FPR_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_photo_user)); + } + else { + s_fpr_fail = 1; + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无对应的用户信息!", + FPR_FAIL, callback); + } + + } + s_fpr_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.state |= 2; + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_fpr_user.cpp b/src/fm_borrow_fpr_user.cpp new file mode 100644 index 0000000..5c482fe --- /dev/null +++ b/src/fm_borrow_fpr_user.cpp @@ -0,0 +1,270 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_fpr_user + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员指纹验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {323, 90, 272, 234, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; + +// if (fpr_open() != 0) { +// printf("fpr open fail.\n"); +// } +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static void form_exit(struct sgi_form *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + //sgi_form_show(&g_sgi_form_get_001); +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// s_timer = 60; +// } +} + +static void btn_card_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_borrow_card_user)); +} + +static void btn_pwd_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_borrow_pwd_user)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + s_fpr_fail = 0; + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + //if (!s_fpr_start) { + // break; + //} + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + play_effect_fpr(); + fpr_module_trigger(FPR_IDENTIFY); + s_fpr_start = 1; + printf("start identify.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无效,请重新采集!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + printf("fpr result: %d\n", r); + r = search_uid(&g_passport, SR_FPR, r); + if (r == 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_FPR_MASK; + g_passport.visit |= USR_FPR_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_manager)); + } + else { + s_fpr_fail = 1; + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无对应的用户信息!", + FPR_FAIL, callback); + } + } + s_fpr_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.state |= 2; + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_photo_user.cpp b/src/fm_borrow_photo_user.cpp new file mode 100644 index 0000000..b5e177f --- /dev/null +++ b/src/fm_borrow_photo_user.cpp @@ -0,0 +1,210 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_photo_user + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员照片比对 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_lbl_uid; /* 编号标签 */ +static union sgi_object s_lbl_name; /* 姓名标签 */ +static union sgi_object s_lbl_dept; /* 部门标签 */ +//static union sgi_object s_lbl_timing; /* 用时标签 */ +static union sgi_object s_upd_time; /* 用时 */ +static union sgi_object s_pho_sample; /* 照片样本 */ +static union sgi_object s_pho_real; /* 实时照片 */ +static union sgi_object s_btn_confirm; /* 确定按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {112, 64, 574, 302, {"photo-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; + + /* 获取照片样本 */ + s_pho_sample.photo.surface = load_photo(&g_passport, PHO_SAMPLE); + if (s_pho_sample.photo.surface) { + s_pho_sample.photo.redraw = 1; + } + + /* 获取实时照片 */ + s_pho_real.photo.surface = load_photo(&g_passport, PHO_REAL); + if (s_pho_real.photo.surface) { + s_pho_real.photo.redraw = 1; + } + printf("load photo end.\n"); + + /* 为人员信息框赋值 */ + set_object_text_u(&s_lbl_uid.label, g_passport.uid); + set_object_text_u(&s_lbl_name.label, g_passport.name); + set_object_text_u(&s_lbl_dept.label, g_passport.dept); +} + +static void form_exit(struct sgi_form *) +{ + printf("unload photo.\n"); + unload_photo(&s_pho_sample.photo); + unload_photo(&s_pho_real.photo); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_confirm_up(struct sgi_button *) +{ + time(&g_passport.borrow_time); + g_passport.return_time = g_passport.borrow_time + + s_upd_time.updown.value * 3600; + sgi_form_show(&FORM_CLASS(fm_borrow_unlock)); +} + +static void btn_back_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_borrow_unlock)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号 */ + LABEL_CREATE(s_lbl_uid, FORM_CLASS(MODULE_NAME), 546, 92, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 姓名 */ + LABEL_CREATE(s_lbl_name, FORM_CLASS(MODULE_NAME), 546, 134, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 部门 */ + LABEL_CREATE(s_lbl_dept, FORM_CLASS(MODULE_NAME), 546, 176, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 用时 */ + //LABEL_CREATE(s_lbl_timing, FORM_CLASS(MODULE_NAME), 588, 220, 35, 40, 1, + // "jht.ttf", 20, text_cl); + //s_lbl_timing.label.align = DT_CENTER; + //set_object_text_w(&s_lbl_timing.label, L"24"); + UPDOWN_CREATE(s_upd_time, FORM_CLASS(MODULE_NAME), 541, 216, 132, 47, 1, + 38, "jht.ttf", 20, text_cl, "updown-u.png", "updown-d.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_upd_time.updown.value = 24; + + /* 照片样本 */ + PHOTO_CREATE(s_pho_sample, FORM_CLASS(MODULE_NAME), 135, 87, 158, 178, 1); + + /* 实时照片 */ + PHOTO_CREATE(s_pho_real, FORM_CLASS(MODULE_NAME), 307, 87, 158, 178, 1); + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 310, 302, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_pwd_manager.cpp b/src/fm_borrow_pwd_manager.cpp new file mode 100644 index 0000000..66e0a12 --- /dev/null +++ b/src/fm_borrow_pwd_manager.cpp @@ -0,0 +1,183 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_pwd_manager + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {165, 59, 377, 95, {"pwd-2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; + s_pwd_retries = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_manager_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + g_passport.visit &= MGR_PWD_MASK; + g_passport.visit |= MGR_PWD_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_photo_user)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 86, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 126, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_pwd_user.cpp b/src/fm_borrow_pwd_user.cpp new file mode 100644 index 0000000..4a16384 --- /dev/null +++ b/src/fm_borrow_pwd_user.cpp @@ -0,0 +1,192 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_pwd_user + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {188, 58, 353, 106, {"pwd-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; + s_pwd_retries = 0; +} + +static void form_exit(struct sgi_form *) +{ + FORM_CLASS(MODULE_NAME).msgbox = NULL; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_user_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_PWD_MASK; + g_passport.visit |= USR_PWD_VALID; + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_manager)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 83, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 123, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_borrow_unlock.cpp b/src/fm_borrow_unlock.cpp new file mode 100644 index 0000000..2b7ad9d --- /dev/null +++ b/src/fm_borrow_unlock.cpp @@ -0,0 +1,258 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_borrow_unlock + +FORM_MODULE(MODULE_NAME); /* 取枪模块,枪柜开锁 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_box; /* 枪柜 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_cell s_box_cell[BOX_NUMS] = { + CELL(15,11,61,40),CELL(79,11,61,40),CELL(143,11,61,40), + CELL(205,11,61,40),CELL(268,11,61,40),CELL(332,11,61,40), + CELL(395,11,61,40),CELL(457,11,61,40),CELL(520,11,61,40), + CELL(584,11,61,40), + + CELL(15,54,61,40),CELL(79,54,61,40),CELL(143,54,61,40), + CELL(205,54,61,40),CELL(268,54,61,40),CELL(332,54,61,40), + CELL(395,54,61,40),CELL(457,54,61,40),CELL(520,54,61,40), + CELL(584,54,61,40), + + CELL(15,96,61,40),CELL(79,96,61,40),CELL(143,96,61,40), + CELL(205,96,61,40),CELL(268,96,61,40),CELL(332,96,61,40), + CELL(395,96,61,40),CELL(457,96,61,40),CELL(520,96,61,40), + CELL(584,96,61,40), + + CELL(15,138,102,77),CELL(121,138,102,77),CELL(227,138,102,77), + CELL(331,138,102,77),CELL(438,138,102,77),CELL(541,138,102,77), + + CELL(15,218,102,77),CELL(121,218,102,77),CELL(227,218,102,77), + CELL(331,218,102,77),CELL(438,218,102,77),CELL(541,218,102,77), +}; + +static struct sgi_widget s_widget[] = { + {69, 55, 658, 308, {"photo-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + u32 i; + struct box_info *info = get_box_info(); + + /* 暂停锁监控 */ + pause_lock_monitor(); + + /* */ + for (i = 0; i < BOX_NUMS; ++i) { + s_box.box.cell[i].state = 0; + s_box.box.cell[i].tag = info[i].state; + //printf("cells[%d].tag: %d\n", i, s_box.box.cell[i].tag); + } + + s_timer = 600; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_main.button.up(&s_btn_main.button); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + int i; + u32 cells[4] = {0}; + struct box_info *info = get_box_info(); + + int has = 0; + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + has = 1; + break; + } + } + + if (!has) { + return; + } + + /* 登记取枪信息 */ + for (i = 0; i < BOX_NUMS; ++i) { + cells[i / 32] |= (s_box.box.cell[i].state & 1) << (i % 32); + } + if (enroll_borrow(&g_passport, cells) != 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"登记取枪信息失败!", 0, NULL); + return; + } + + /* 记录取枪日志 */ + //struct log_borrow borrow; + int nums = 0; + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + record_borrow_log(&g_passport, &info[i]); + nums++; +// memset(&borrow, 0, sizeof(struct log_borrow)); +// borrow.id = get_log_no(LOG_BORROW); +// time(&borrow.time); +// sgi_ncp16(borrow.name, g_passport.name, +// COUNTOF(borrow.name)); +// sgi_ncp16(borrow.gun_type, info[i].gun_model, +// COUNTOF(borrow.gun_type)); +// sgi_ncp16(borrow.gun_code, info[i].gun_code, +// COUNTOF(borrow.gun_code)); +// sgi_append_log(DBL(borrow), &borrow, +// sizeof(struct log_borrow)); + } + } + + /* 记录上报数据 */ + recorcd_borrow_report(&g_passport, 0, nums); + + /* 打开枪柜门 */ + authorize_open_door(); + + /* 打开对应枪锁 */ + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + if (i2c_comm_unlock(s_box.box.cell_addr[i]) == 0) { + SDL_Delay(2000); + } + } + } + + msgbox(&FORM_CLASS(MODULE_NAME), L"请在规定的时间内领取枪械并关闭柜门!", + SUCCESS, callback); +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 32, 150, 22, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 枪柜表格 */ + BOX_CREATE(s_box, FORM_CLASS(MODULE_NAME), 69, 55, 658, 308, 1, + "jht.ttf", 20, color, "box-0.png", "box-1.png", "box-2.png", + "box-3.png",IMG_OPTIMIZE | IMG_ALPHA, s_box_cell); + s_box.box.cell_addr = g_box_addr; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 346, 383, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_box_manage.cpp b/src/fm_box_manage.cpp new file mode 100644 index 0000000..933904b --- /dev/null +++ b/src/fm_box_manage.cpp @@ -0,0 +1,159 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_box_manage + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_init; /* 枪弹柜初始化 */ +static union sgi_object s_btn_info; /* 枪械信息查询 */ +static union sgi_object s_btn_status; /* 枪弹柜状态 */ +static union sgi_object s_btn_remote_unlock; /* 远程开锁 */ +static union sgi_object s_btn_urgent_unlock; /* 紧急开锁 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_init_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_return_fpr_user)); +} + +static void btn_info_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_status_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_remote_unlock_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_urgent_unlock_up(struct sgi_button *) +{ + /* 进入紧急开开锁必须由两个管理确认, 调用管理员密码验证窗口 */ + sgi_form_show(&FORM_CLASS(fm_unlock_pwd)); + //sgi_form_show(&FORM_CLASS(fm_unlock)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 枪弹柜初始化 */ + BUTTON_CREATE(s_btn_init, FORM_CLASS(MODULE_NAME), 266, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-init.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_init.button.up = btn_init_up; + + /* 枪械信息查询 */ + BUTTON_CREATE(s_btn_info, FORM_CLASS(MODULE_NAME), 409, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-info-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_info.button.up = btn_info_up; + + /* 枪弹柜状态查询 */ + BUTTON_CREATE(s_btn_status, FORM_CLASS(MODULE_NAME), 200, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-status.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_status.button.up = btn_status_up; + + /* 远程开锁 */ + BUTTON_CREATE(s_btn_remote_unlock, FORM_CLASS(MODULE_NAME), 340, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-unlock.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_remote_unlock.button.up = btn_remote_unlock_up; + + /* 远程开锁 */ + BUTTON_CREATE(s_btn_urgent_unlock, FORM_CLASS(MODULE_NAME), 480, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-unlock-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_urgent_unlock.button.up = btn_urgent_unlock_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_chpwd.cpp b/src/fm_chpwd.cpp new file mode 100644 index 0000000..12ed6d6 --- /dev/null +++ b/src/fm_chpwd.cpp @@ -0,0 +1,230 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_chpwd + +FORM_MODULE(MODULE_NAME); /* 密码修改模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_old_pwd; /* 旧密码 */ +static union sgi_object s_edt_new_pwd; /* 新密码 */ +static union sgi_object s_edt_confirm_pwd; /* 确认新密码 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[] = { + {100, 44, 519, 173, {"chpwd.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_old_pwd.edit, NULL); + set_object_text_u(&s_edt_new_pwd.edit, NULL); + set_object_text_u(&s_edt_confirm_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 120; + s_pwd_retries = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_main.button.up(&s_btn_main.button); + } + else if (user == PWD_NOT_MATCH) { + set_object_focus(&s_edt_confirm_pwd); + } + else if (user == PWD_SHORTEST) { + set_object_focus(&s_edt_new_pwd); + } + else if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_old_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r; + + /* 检查两次所输入新密码是否一致 */ + if (sgi_ncmp16(s_edt_new_pwd.edit.text, s_edt_confirm_pwd.edit.text, + COUNTOF(s_edt_new_pwd.edit.text)) != 0) { + printf("confirm pwd fail.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"两次输入密码不一致!", + PWD_NOT_MATCH, callback); + return; + } + + /* 检查密码长度是否符合要求 */ + if ((r = sgi_len16(s_edt_new_pwd.edit.text)) < MIN_PWD_LEN) { + printf("pwd is shortest.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"密码长度应大于6个字符!", + PWD_SHORTEST, callback); + return; + } + printf("pwd len: %d\n", r); + + /* 提交修改并验证用户及旧密码是否有效 */ + r = change_pwd(s_edt_uid.edit.text, s_edt_old_pwd.edit.text, + s_edt_new_pwd.edit.text); + if (r == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码修改成功!", + SUCCESS, callback); + + /* log */ + record_system_log(s_edt_uid.edit.text, L"成功修改用户密码"); + } + else if (r == ID_INVALID) { + printf("invalid user.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"旧密码无效!", + PWD_INVALID, callback); + + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 375, 65, 222, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 旧密码 */ + EDIT_CREATE(s_edt_old_pwd, FORM_CLASS(MODULE_NAME), 375, 101, 222, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_old_pwd.edit.pwdchar = 1; + + /* 新密码 */ + EDIT_CREATE(s_edt_new_pwd, FORM_CLASS(MODULE_NAME), 375, 137, 222, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_new_pwd.edit.pwdchar = 1; + + /* 确认新密码 */ + EDIT_CREATE(s_edt_confirm_pwd, FORM_CLASS(MODULE_NAME), 375, 173, 222, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_confirm_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 623, 156, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_download.cpp b/src/fm_download.cpp new file mode 100644 index 0000000..4095ef9 --- /dev/null +++ b/src/fm_download.cpp @@ -0,0 +1,240 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_download + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_vendor; /* */ +static union sgi_object s_lbl_product; /* */ +static union sgi_object s_lbl_sn; /* */ +static union sgi_object s_lbl_total; /* */ +static union sgi_object s_lbl_avail; /* */ +static union sgi_object s_btn_incre; /* */ +static union sgi_object s_btn_full; /* */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {130, 25, 541, 276, {"download.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 s_udisk_exist = 0; +static struct udisk_info s_udisk; + +static void form_enter(struct sgi_form *) +{ + set_object_text_u(&s_lbl_vendor.label, NULL); + set_object_text_u(&s_lbl_product.label, NULL); + set_object_text_u(&s_lbl_sn.label, NULL); + set_object_text_u(&s_lbl_total.label, NULL); + set_object_text_u(&s_lbl_avail.label, NULL); + + s_udisk_exist = 0; + s_btn_incre.button.state |= 2; + s_btn_full.button.state |= 2; +} + +static void form_exit(struct sgi_form *) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void callback(s32 user) +{ + s_btn_back.button.up(&s_btn_back.button); +} + +static void btn_incre_up(struct sgi_button *) +{ + s32 count = 0; + wchar_t buf[64]; + + if (!s_udisk_exist) { + return; + } + + count = download_log(0); + swprintf(buf, COUNTOF(buf), L"[%d]条数据下载完成!", count); + msgbox(&FORM_CLASS(MODULE_NAME), buf, 0, callback); +} + +static void btn_full_up(struct sgi_button *) +{ + if (!s_udisk_exist) { + return; + } + + download_log(1); + + msgbox(&FORM_CLASS(MODULE_NAME), L"数据下载完成!", 0, callback); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + static u32 cycle = 0; + + /* per 1s check device */ + if (TIME_AFTER(SDL_GetTicks(), cycle)) { + if (!s_udisk_exist) { + if (udisk_insert_detect(&s_udisk) == 0) { + sgi_cpa2u(s_lbl_vendor.label.caption, + s_udisk.vendor); + sgi_cpa2u(s_lbl_product.label.caption, + s_udisk.product); + sgi_cpa2u(s_lbl_sn.label.caption, s_udisk.sn); + + if (s_udisk.total > 1024) { + sgi_sprintf16(s_lbl_total.label.caption, + L"%.2f GB", + s_udisk.total / 1024.0f); + } + else { + sgi_sprintf16(s_lbl_total.label.caption, + L"%d MB", s_udisk.total); + } + + if (s_udisk.avail > 1024) { + sgi_sprintf16(s_lbl_avail.label.caption, + L"%.2f GB", + s_udisk.avail / 1024.0f); + } + else { + sgi_sprintf16(s_lbl_avail.label.caption, + L"%d MB", s_udisk.avail); + } + + s_udisk_exist = 1; + s_btn_incre.button.state &= ~2; + s_btn_full.button.state &= ~2; + + FORM_CLASS(MODULE_NAME).redraw = 1; + } + } + else { + if (udisk_remove_detect()) { + set_object_text_u(&s_lbl_vendor.label, NULL); + set_object_text_u(&s_lbl_product.label, NULL); + set_object_text_u(&s_lbl_sn.label, NULL); + set_object_text_u(&s_lbl_total.label, NULL); + set_object_text_u(&s_lbl_avail.label, NULL); + + s_udisk_exist = 0; + s_btn_incre.button.state |= 2; + s_btn_full.button.state |= 2; + + FORM_CLASS(MODULE_NAME).redraw = 1; + } + } + cycle = SDL_GetTicks() + 1000; + } + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + LABEL_CREATE(s_lbl_vendor, FORM_CLASS(MODULE_NAME), 353, 128, 338, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_product, FORM_CLASS(MODULE_NAME), 353, 166, 338, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_sn, FORM_CLASS(MODULE_NAME), 353, 199, 338, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_total, FORM_CLASS(MODULE_NAME), 353, 231, 338, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_avail, FORM_CLASS(MODULE_NAME), 353, 262, 338, 25, 1, + "jht.ttf", 24, color); + + /* */ + BUTTON_CREATE(s_btn_incre, FORM_CLASS(MODULE_NAME), 265, 319, 110, 45, 1, + "btn-incre-u.png", "btn-incre-d.png", "btn-incre-e.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_incre.button.up = btn_incre_up; + + /* */ + BUTTON_CREATE(s_btn_full, FORM_CLASS(MODULE_NAME), 425, 319, 110, 45, 1, + "btn-full-u.png", "btn-full-d.png", "btn-full-e.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_full.button.up = btn_full_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_info_choice.cpp b/src/fm_info_choice.cpp new file mode 100644 index 0000000..233d4b6 --- /dev/null +++ b/src/fm_info_choice.cpp @@ -0,0 +1,121 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_info_choice + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_register; /* 注册 */ +static union sgi_object s_btn_stat; /* 统计 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_register_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_stat_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 注册 */ + BUTTON_CREATE(s_btn_register, FORM_CLASS(MODULE_NAME), 269, 176, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-reg.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_register.button.up = btn_register_up; + + /* 统计 */ + BUTTON_CREATE(s_btn_stat, FORM_CLASS(MODULE_NAME), 409, 176, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-stat.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_stat.button.up = btn_stat_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_info_register.cpp b/src/fm_info_register.cpp new file mode 100644 index 0000000..94fae9b --- /dev/null +++ b/src/fm_info_register.cpp @@ -0,0 +1,162 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_info_register + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_unit; /* 单位信息 */ +static union sgi_object s_btn_person; /* 人员信息 */ +static union sgi_object s_btn_gun; /* 枪支信息 */ +static union sgi_object s_btn_bullet; /* 弹药信息 */ +static union sgi_object s_btn_box; /* 枪弹柜信息 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_unit_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_unit)); +} + +static void btn_person_up(struct sgi_button *) +{ + /* */ + person_reg_data_clear(); + g_passport.reg_flag = REG_NEW; + g_data_update_state = REG_NEW; + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void btn_gun_up(struct sgi_button *) +{ + //g_data_update_state = REG_NEW; + sgi_form_show(&FORM_CLASS(fm_reg_gun)); +} + +static void btn_bullet_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_bullet)); +} + +static void btn_box_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_box)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_choice)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 单位信息 */ + BUTTON_CREATE(s_btn_unit, FORM_CLASS(MODULE_NAME), 265, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-unit.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_unit.button.up = btn_unit_up; + + /* 人员信息 */ + BUTTON_CREATE(s_btn_person, FORM_CLASS(MODULE_NAME), 409, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-person.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_person.button.up = btn_person_up; + + /* 枪支信息 */ + BUTTON_CREATE(s_btn_gun, FORM_CLASS(MODULE_NAME), 201, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-gun.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_gun.button.up = btn_gun_up; + + /* 弹药信息 */ + BUTTON_CREATE(s_btn_bullet, FORM_CLASS(MODULE_NAME), 340, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-bullet.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_bullet.button.up = btn_bullet_up; + + /* 枪弹柜信息 */ + BUTTON_CREATE(s_btn_box, FORM_CLASS(MODULE_NAME), 479, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-box-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_box.button.up = btn_box_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_info_stat.cpp b/src/fm_info_stat.cpp new file mode 100644 index 0000000..19e9d6f --- /dev/null +++ b/src/fm_info_stat.cpp @@ -0,0 +1,157 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_info_stat + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_unit; /* 单位信息 */ +static union sgi_object s_btn_person; /* 人员信息 */ +static union sgi_object s_btn_gun; /* 枪支信息 */ +static union sgi_object s_btn_bullet; /* 弹药信息 */ +static union sgi_object s_btn_box; /* 枪弹柜信息 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_unit_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_unit)); +} + +static void btn_person_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_stat_person)); +} + +static void btn_gun_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_stat_gun)); +} + +static void btn_bullet_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_stat_bullet)); +} + +static void btn_box_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_box)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_choice)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 单位信息 */ + BUTTON_CREATE(s_btn_unit, FORM_CLASS(MODULE_NAME), 265, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-unit.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_unit.button.up = btn_unit_up; + + /* 人员信息 */ + BUTTON_CREATE(s_btn_person, FORM_CLASS(MODULE_NAME), 409, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-person.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_person.button.up = btn_person_up; + + /* 枪支信息 */ + BUTTON_CREATE(s_btn_gun, FORM_CLASS(MODULE_NAME), 201, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-gun.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_gun.button.up = btn_gun_up; + + /* 弹药信息 */ + BUTTON_CREATE(s_btn_bullet, FORM_CLASS(MODULE_NAME), 340, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-bullet.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_bullet.button.up = btn_bullet_up; + + /* 枪弹柜信息 */ + BUTTON_CREATE(s_btn_box, FORM_CLASS(MODULE_NAME), 479, 243, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-box-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_box.button.up = btn_box_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_level.cpp b/src/fm_level.cpp new file mode 100644 index 0000000..0100b36 --- /dev/null +++ b/src/fm_level.cpp @@ -0,0 +1,145 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_level + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_level; /* 身份权限设置 */ +static union sgi_object s_btn_spec; /* 特殊权限设置 */ +static union sgi_object s_btn_pwd; /* 管理员密码设置 */ +static union sgi_object s_btn_logon; /* 登录方式设定 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_level_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_user_level)); +} + +static void btn_spec_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_pwd_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_logon_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 身份权限设置 */ + BUTTON_CREATE(s_btn_level, FORM_CLASS(MODULE_NAME), 269, 127, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-level-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_level.button.up = btn_level_up; + + /* 特殊权限设置 */ + BUTTON_CREATE(s_btn_spec, FORM_CLASS(MODULE_NAME), 408, 127, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-spec.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_spec.button.up = btn_spec_up; + + /* 管理员密码设置 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 269, 240, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-pwd.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /*登录方式设置 */ + BUTTON_CREATE(s_btn_logon, FORM_CLASS(MODULE_NAME), 408, 240, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-logon.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_logon.button.up = btn_logon_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_alarm.cpp b/src/fm_log_alarm.cpp new file mode 100644 index 0000000..391c558 --- /dev/null +++ b/src/fm_log_alarm.cpp @@ -0,0 +1,343 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_alarm + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct log_alarm *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct log_alarm *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + read_count = s_record_count - offset; + p = s_grid_data + read_count - 1; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + //sgi_ncpa2u(object->cells[index].string, p->id, + // COUNTOF(p->id)); + sgi_sprintf16(object->cells[index].string, + L"%05d", p->id); + break; + + case 2: /* column 2 */ + tmlocal = localtime(&p->time); + sgi_sprintf16(object->cells[index].string, + L"%02d/%02d", tmlocal->tm_mon + 1, + tmlocal->tm_mday); + break; + + case 3: /* column 3 */ + sgi_ncp16(object->cells[index].string, p->content, + COUNTOF(p->content)); + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p--; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 4; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 33; + object->cells[index].y = y0; + object->cells[index].w = 55; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 89; + object->cells[index].y = y0; + object->cells[index].w = 98; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 188; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 289; + object->cells[index].y = y0; + object->cells[index].w = 313; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct log_alarm *)sgi_log_open(DBL(alarm), &s_data_size); + s_record_count = s_data_size / sizeof(struct log_alarm); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "log-alarm.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.readonly = 1; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_borrow.cpp b/src/fm_log_borrow.cpp new file mode 100644 index 0000000..bf281b0 --- /dev/null +++ b/src/fm_log_borrow.cpp @@ -0,0 +1,382 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_borrow + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct log_borrow *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct log_borrow *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + read_count = s_record_count - offset; + p = s_grid_data + read_count - 1; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + //sgi_ncpa2u(object->cells[index].string, p->id, + // COUNTOF(p->id)); + sgi_sprintf16(object->cells[index].string, + L"%05d", p->id); + break; + + case 2: /* column 2 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 3: /* column 3 */ + tmlocal = localtime(&p->time); + sgi_sprintf16(object->cells[index].string, + L"%02d/%02d", tmlocal->tm_mon + 1, + tmlocal->tm_mday); + break; + + case 4: /* column 4 */ + sgi_ncp16(object->cells[index].string, p->gun_type, + COUNTOF(p->gun_type)); + break; + + case 5: /* column 5 */ + sgi_ncp16(object->cells[index].string, p->gun_code, + COUNTOF(p->gun_code)); + break; + + case 6: /* column 6 */ + sgi_sprintf16(object->cells[index].string, + L"%d", p->bullets); + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p--; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 7; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 23; + object->cells[index].y = y0; + object->cells[index].w = 44; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 68; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 158; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 249; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 340; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 5: /* column 5 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 430; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 6: /* column 6 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 521; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct log_borrow *)sgi_log_open(DBL(borrow), &s_data_size); + s_record_count = s_data_size / sizeof(struct log_borrow); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "log-borrow.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.readonly = 1; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_main.cpp b/src/fm_log_main.cpp new file mode 100644 index 0000000..b12bed5 --- /dev/null +++ b/src/fm_log_main.cpp @@ -0,0 +1,157 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_main + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_borrow; /* 领取枪弹日志 */ +static union sgi_object s_btn_return; /* 归还枪弹日志 */ +static union sgi_object s_btn_alarm; /* 异常报警日志 */ +static union sgi_object s_btn_system; /* 系统操作日志 */ +static union sgi_object s_btn_manager; /* 管理员日志 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_borrow_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_borrow)); +} + +static void btn_return_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_return)); +} + +static void btn_alarm_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_alarm)); +} + +static void btn_system_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_system)); +} + +static void btn_manager_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_manager)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 领取枪弹日志 */ + BUTTON_CREATE(s_btn_borrow, FORM_CLASS(MODULE_NAME), 409, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-borrow.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_borrow.button.up = btn_borrow_up; + + /* 归还枪弹日志 */ + BUTTON_CREATE(s_btn_return, FORM_CLASS(MODULE_NAME), 200, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-return.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_return.button.up = btn_return_up; + + /* 异常报警日志 */ + BUTTON_CREATE(s_btn_alarm, FORM_CLASS(MODULE_NAME), 340, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-alarm.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_alarm.button.up = btn_alarm_up; + + /* 系统操作日志 */ + BUTTON_CREATE(s_btn_system, FORM_CLASS(MODULE_NAME), 480, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-system-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_system.button.up = btn_system_up; + + /* 管理员日志 */ + BUTTON_CREATE(s_btn_manager, FORM_CLASS(MODULE_NAME), 266, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-manager.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_manager.button.up = btn_manager_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_manager.cpp b/src/fm_log_manager.cpp new file mode 100644 index 0000000..7aa69cb --- /dev/null +++ b/src/fm_log_manager.cpp @@ -0,0 +1,356 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_manager + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct log_manager *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct log_manager *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + read_count = s_record_count - offset; + p = s_grid_data + read_count - 1; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + //sgi_ncpa2u(object->cells[index].string, p->id, + // COUNTOF(p->id)); + sgi_sprintf16(object->cells[index].string, + L"%05d", p->id); + break; + + case 2: /* column 2 */ + tmlocal = localtime(&p->time); + sgi_sprintf16(object->cells[index].string, + L"%02d/%02d", tmlocal->tm_mon + 1, + tmlocal->tm_mday); + break; + + case 3: /* column 3 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 4: /* column 4 */ + sgi_ncp16(object->cells[index].string, p->content, + COUNTOF(p->content)); + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p--; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 5; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 27; + object->cells[index].y = y0; + object->cells[index].w = 44; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 71; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 170; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 270; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 369; + object->cells[index].y = y0; + object->cells[index].w = 237; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct log_manager *)sgi_log_open(DBL(manager), &s_data_size); + s_record_count = s_data_size / sizeof(struct log_manager); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "log-manager.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.readonly = 1; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_return.cpp b/src/fm_log_return.cpp new file mode 100644 index 0000000..98ea00a --- /dev/null +++ b/src/fm_log_return.cpp @@ -0,0 +1,382 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_return + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct log_borrow *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct log_borrow *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + read_count = s_record_count - offset; + p = s_grid_data + read_count - 1; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + //sgi_ncpa2u(object->cells[index].string, p->id, + // COUNTOF(p->id)); + sgi_sprintf16(object->cells[index].string, + L"%05d", p->id); + break; + + case 2: /* column 2 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 3: /* column 3 */ + tmlocal = localtime(&p->time); + sgi_sprintf16(object->cells[index].string, + L"%02d/%02d", tmlocal->tm_mon + 1, + tmlocal->tm_mday); + break; + + case 4: /* column 4 */ + sgi_ncp16(object->cells[index].string, p->gun_type, + COUNTOF(p->gun_type)); + break; + + case 5: /* column 5 */ + sgi_ncp16(object->cells[index].string, p->gun_code, + COUNTOF(p->gun_code)); + break; + + case 6: /* column 6 */ + sgi_sprintf16(object->cells[index].string, + L"%d", p->bullets); + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p--; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 7; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 23; + object->cells[index].y = y0; + object->cells[index].w = 44; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 68; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 158; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 249; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 340; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 5: /* column 5 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 430; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + case 6: /* column 6 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 521; + object->cells[index].y = y0; + object->cells[index].w = 90; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct log_borrow *)sgi_log_open(DBL(back), &s_data_size); + s_record_count = s_data_size / sizeof(struct log_borrow); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "log-return.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.readonly = 1; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_log_system.cpp b/src/fm_log_system.cpp new file mode 100644 index 0000000..96e3828 --- /dev/null +++ b/src/fm_log_system.cpp @@ -0,0 +1,356 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_log_system + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct log_system *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct log_system *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + read_count = s_record_count - offset; + p = s_grid_data + read_count - 1; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + //sgi_ncpa2u(object->cells[index].string, p->id, + // COUNTOF(p->id)); + sgi_sprintf16(object->cells[index].string, + L"%05d", p->id); + break; + + case 2: /* column 2 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 3: /* column 3 */ + tmlocal = localtime(&p->time); + sgi_sprintf16(object->cells[index].string, + L"%02d/%02d", tmlocal->tm_mon + 1, + tmlocal->tm_mday); + break; + + case 4: /* column 4 */ + sgi_ncp16(object->cells[index].string, p->content, + COUNTOF(p->content)); + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p--; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 5; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 27; + object->cells[index].y = y0; + object->cells[index].w = 44; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 71; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 170; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 270; + object->cells[index].y = y0; + object->cells[index].w = 99; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 369; + object->cells[index].y = y0; + object->cells[index].w = 237; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct log_system *)sgi_log_open(DBL(syslog), &s_data_size); + s_record_count = s_data_size / sizeof(struct log_system); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "log-system.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.readonly = 1; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_main.cpp b/src/fm_main.cpp new file mode 100644 index 0000000..af9ca5d --- /dev/null +++ b/src/fm_main.cpp @@ -0,0 +1,211 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_main + +FORM_MODULE(MODULE_NAME); /* 领还枪主模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_idt_power; +static union sgi_object s_idt_net; +static union sgi_object s_btn_borrow; /* 领取按钮 */ +static union sgi_object s_btn_return; /* 归还按钮 */ +static union sgi_object s_btn_chpwd; /* 修改密码按钮 */ +static union sgi_object s_btn_current; /* 当前页面指示 */ +static union sgi_object s_btn_menu; /* 回到主菜单按钮 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + u16 buf[32] = {0};//(u16)L'枪',(u16)L'柜',(u16)L'编',(u16)L'号',(u16)L':'}; + + /* 关闭指纹模块 */ + //if (fpr_close() != 0) { + // printf("fpr close fail.\n"); + //} + //power_ctrl(0); + /* 打开锁监控 */ + resume_lock_monitor(); + + /* */ + sgi_sprintf16(buf, L"枪柜编号: "); + sgi_ncp16(&buf[6], get_box_code(), 16); + set_object_text_u(&s_lbl_code.label, buf); +} + +static void form_exit(struct sgi_form *) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_borrow_up(struct sgi_button *) +{ + /* 打开指纹模块 */ + //power_ctrl(1); + //SDL_Delay(200); +// if (fpr_open() != 0) { +// printf("fpr open fail.\n"); +// } + + /* 清零通行记录数据 */ + memset(&g_passport, 0, sizeof(struct passport_data)); + + sgi_form_show(&FORM_CLASS(fm_borrow_fpr_user)); +} + +static void btn_return_up(struct sgi_button *) +{ + /* 打开指纹模块 */ + //power_ctrl(1); + //SDL_Delay(200); + //if (fpr_open() != 0) { + // printf("fpr open fail.\n"); + //} + + /* 清零通行记录数据 */ + memset(&g_passport, 0, sizeof(struct passport_data)); + + sgi_form_show(&FORM_CLASS(fm_return_fpr_user)); +} + +static void btn_chpwd_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_menu_up(struct sgi_button *) +{ + /* 清零通行记录数据 */ + memset(&g_passport, 0, sizeof(struct passport_data)); + + /* 调用管理员密码验证窗口 */ + sgi_form_show(&FORM_CLASS(fm_menu_pwd)); +} + +static s32 form_frame(struct sgi_form *form) +{ + static u32 next_time = 0; + s32 status; + + if (TIME_AFTER(SDL_GetTicks(), next_time)) { + status = get_power_status(); + if (s_idt_power.indicator.state != status) { + s_idt_power.indicator.state = status; + s_idt_power.indicator.redraw = 1; + } + + status = get_net_link_status(); + if (s_idt_net.indicator.state != status) { + s_idt_net.indicator.state = status; + s_idt_net.indicator.redraw = 1; + } + next_time = SDL_GetTicks() + 1000; + } + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + + /* */ + INDICATOR_CREATE(s_idt_power, FORM_CLASS(MODULE_NAME), 698, 429, 35, 35, 1, + "ac.png", "battery.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + INDICATOR_CREATE(s_idt_net, FORM_CLASS(MODULE_NAME), 744, 429, 35, 35, 1, + "net-down.png", "net-link.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* 取枪按钮 */ + BUTTON_CREATE(s_btn_borrow, FORM_CLASS(MODULE_NAME), 190, 184, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-borrow-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_borrow.button.up = btn_borrow_up; + + /* 还枪按钮 */ + BUTTON_CREATE(s_btn_return, FORM_CLASS(MODULE_NAME), 330, 184, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-return-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_return.button.up = btn_return_up; + + /* 密码修改按钮 */ + BUTTON_CREATE(s_btn_chpwd, FORM_CLASS(MODULE_NAME), 470, 184, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-chpwd.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_chpwd.button.up = btn_chpwd_up; + + /* 归还枪弹按钮 */ + BUTTON_CREATE(s_btn_current, FORM_CLASS(MODULE_NAME), 260, 315, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-main.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_current.button.state |= 2; + + /* 主菜单按钮 */ + BUTTON_CREATE(s_btn_menu, FORM_CLASS(MODULE_NAME), 407, 315, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-menu.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_menu.button.up = btn_menu_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_menu.cpp b/src/fm_menu.cpp new file mode 100644 index 0000000..7287512 --- /dev/null +++ b/src/fm_menu.cpp @@ -0,0 +1,153 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_menu + +FORM_MODULE(MODULE_NAME); /* 主菜单模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_info; /* 信息管理按钮 */ +static union sgi_object s_btn_level; /* 权限管理按钮 */ +static union sgi_object s_btn_box; /* 枪弹柜管理按钮 */ +static union sgi_object s_btn_log; /* 使用日志按钮 */ +static union sgi_object s_btn_system; /* 系统管理按钮 */ +static union sgi_object s_btn_main; /* 领还枪弹按钮 */ +static union sgi_object s_btn_menu; /* 回到主菜单按钮 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_info_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_choice)); +} + +static void btn_level_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_level)); +} + +static void btn_box_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_box_manage)); +} + +static void btn_log_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_system_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_system)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 信息管理按钮 */ + BUTTON_CREATE(s_btn_info, FORM_CLASS(MODULE_NAME), 270, 94, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-info.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_info.button.up = btn_info_up; + + /* 权限管理按钮 */ + BUTTON_CREATE(s_btn_level, FORM_CLASS(MODULE_NAME), 410, 94, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-level.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_level.button.up = btn_level_up; + + /*枪弹柜管理按钮 */ + BUTTON_CREATE(s_btn_box, FORM_CLASS(MODULE_NAME), 200, 206, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-box.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_box.button.up = btn_box_up; + + + /*使用日志按钮 */ + BUTTON_CREATE(s_btn_log, FORM_CLASS(MODULE_NAME), 340, 206, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-log.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_log.button.up = btn_log_up; + + /*系统管理按钮 */ + BUTTON_CREATE(s_btn_system, FORM_CLASS(MODULE_NAME), 480, 206, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-system.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_system.button.up = btn_system_up; + + /* 领还枪弹按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 260, 315, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-main.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 主菜单按钮 */ + BUTTON_CREATE(s_btn_menu, FORM_CLASS(MODULE_NAME), 407, 315, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-menu.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_menu.button.state |= 2; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_menu_pwd.cpp b/src/fm_menu_pwd.cpp new file mode 100644 index 0000000..fbd45fd --- /dev/null +++ b/src/fm_menu_pwd.cpp @@ -0,0 +1,184 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_menu_pwd + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {165, 59, 377, 95, {"pwd-2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; + s_pwd_retries = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_manager_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + g_passport.visit &= MGR_PWD_MASK; + g_passport.visit |= MGR_PWD_VALID; + sgi_form_show(&FORM_CLASS(fm_menu)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 86, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 126, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_mon_setting.cpp b/src/fm_mon_setting.cpp new file mode 100644 index 0000000..110516c --- /dev/null +++ b/src/fm_mon_setting.cpp @@ -0,0 +1,240 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_mon_setting + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_chk_door; +static union sgi_object s_chk_door_ex; +static union sgi_object s_chk_lock; +static union sgi_object s_chk_power; +static union sgi_object s_chk_borrow; +static union sgi_object s_chk_pwd; +static union sgi_object s_lbl_door; /* */ +static union sgi_object s_lbl_door_ex; /* */ +static union sgi_object s_lbl_lock; /* */ +static union sgi_object s_lbl_power; /* */ +static union sgi_object s_lbl_borrow; /* */ +static union sgi_object s_lbl_pwd; /* */ +static union sgi_object s_btn_confirm; /* */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {127, 113, 547, 179, {"unlock.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s32 flags; + + flags = get_alarm_setting(); + if (flags & ALARM_DOOR_EN) { + s_chk_door.check.value = 1; + } + else { + s_chk_door.check.value = 0; + } + + if (flags & ALARM_DOOR_EX_EN) { + s_chk_door_ex.check.value = 1; + } + else { + s_chk_door_ex.check.value = 0; + } + + if (flags & ALARM_LOCK_EN) { + s_chk_lock.check.value = 1; + } + else { + s_chk_lock.check.value = 0; + } + + if (flags & ALARM_POWER_EN) { + s_chk_power.check.value = 1; + } + else { + s_chk_power.check.value = 0; + } + + if (flags & ALARM_BORROW_EN) { + s_chk_borrow.check.value = 1; + } + else { + s_chk_borrow.check.value = 0; + } + + if (flags & ALARM_PWD_EN) { + s_chk_pwd.check.value = 1; + } + else { + s_chk_pwd.check.value = 0; + } +} + +static void form_exit(struct sgi_form *) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 flags = 0; + + if (s_chk_door.check.value) { + flags |= ALARM_DOOR_EN; + } + + if (s_chk_door_ex.check.value) { + flags |= ALARM_DOOR_EX_EN; + } + + if (s_chk_lock.check.value) { + flags |= ALARM_LOCK_EN; + } + + if (s_chk_power.check.value) { + flags |= ALARM_POWER_EN; + } + + if (s_chk_borrow.check.value) { + flags |= ALARM_BORROW_EN; + } + + if (s_chk_pwd.check.value) { + flags |= ALARM_PWD_EN; + } + + printf("mon set: 0x%x\n", flags); + + setup_alarm(flags); + + s_btn_back.button.up(&s_btn_back.button); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_system)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + LABEL_CREATE(s_lbl_door, FORM_CLASS(MODULE_NAME), 220, 95, 460, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_door.label, L"枪柜门锁监控"); + + LABEL_CREATE(s_lbl_door_ex, FORM_CLASS(MODULE_NAME), 480, 95, 200, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_door_ex.label, L"柜门辅助监控"); + + LABEL_CREATE(s_lbl_lock, FORM_CLASS(MODULE_NAME), 220, 138, 460, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_lock.label, L"枪锁监控"); + + LABEL_CREATE(s_lbl_power, FORM_CLASS(MODULE_NAME), 220, 181, 460, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_power.label, L"枪柜断电报警"); + + LABEL_CREATE(s_lbl_borrow, FORM_CLASS(MODULE_NAME), 220, 224, 460, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_borrow.label, L"超时还枪报警"); + + LABEL_CREATE(s_lbl_pwd, FORM_CLASS(MODULE_NAME), 220, 267, 460, 43, 1, + "jht.ttf", 26, color); + set_object_text_w(&s_lbl_pwd.label, L"三次输入错误密码报警"); + + CHECK_CREATE(s_chk_door, FORM_CLASS(MODULE_NAME), 160, 105, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + CHECK_CREATE(s_chk_door_ex, FORM_CLASS(MODULE_NAME), 420, 105, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + CHECK_CREATE(s_chk_lock, FORM_CLASS(MODULE_NAME), 160, 148, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + CHECK_CREATE(s_chk_power, FORM_CLASS(MODULE_NAME), 160, 191, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + CHECK_CREATE(s_chk_borrow, FORM_CLASS(MODULE_NAME), 160, 234, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + CHECK_CREATE(s_chk_pwd, FORM_CLASS(MODULE_NAME), 160, 277, 43, 23, 1, + "chk-unsel.png", "chk-sel.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 333, 325, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_box.cpp b/src/fm_reg_box.cpp new file mode 100644 index 0000000..1d7c939 --- /dev/null +++ b/src/fm_reg_box.cpp @@ -0,0 +1,275 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_box + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_cap; /* */ +static union sgi_object s_edt_manager; /* */ +static union sgi_object s_edt_code; /* */ +static union sgi_object s_edt_model; /* */ +static union sgi_object s_edt_unit; /* */ +static union sgi_object s_rad_gun; /* */ +static union sgi_object s_rad_bullet; /* */ +static union sgi_object s_btn_save; /* 返回按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {102, 45, 546, 179, {"box-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void load_data(void) +{ + struct box_data *box; + size_t size; + + /* */ + box = (struct box_data *)open_r(DBD(gun_box), &size); + if (!box || size != sizeof(struct box_data)) { + set_object_text_u(&s_edt_cap.edit, NULL); + set_object_text_u(&s_edt_code.edit, NULL); + set_object_text_u(&s_edt_manager.edit, NULL); + set_object_text_u(&s_edt_model.edit, NULL); + set_object_text_u(&s_edt_unit.edit, NULL); + s_rad_gun.radio.value = 0; + s_rad_bullet.radio.value = 0; + } + else { + set_object_text_u(&s_edt_code.edit, box->code); + set_object_text_u(&s_edt_model.edit, box->model); + set_object_text_u(&s_edt_manager.edit, box->manager); + set_object_text_u(&s_edt_unit.edit, box->unit); + sgi_sprintf16(s_edt_cap.edit.text, L"%d", box->cap); + if (box->type == BOX_TYPE_BULLET) { + s_rad_gun.radio.value = 0; + s_rad_bullet.radio.value = 1; + } + else { + + s_rad_gun.radio.value = 1; + s_rad_bullet.radio.value = 0; + } + } + + if (box) { + close_r(box, size); + } +} + +static void form_enter(struct sgi_form *) +{ + /* */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* */ + load_data(); + + /* */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == REGISTER_FAIL) { + set_object_focus(&s_edt_code); + } +} + +static void btn_save_up(struct sgi_button *object) +{ + s32 r; + struct box_data box; + + /* */ + memset(&box, 0, sizeof(struct box_data)); + sgi_cp16(box.code, s_edt_code.edit.text); + sgi_cp16(box.model, s_edt_model.edit.text); + sgi_cp16(box.manager, s_edt_manager.edit.text); + sgi_cp16(box.unit, s_edt_unit.edit.text); + box.cap = sgi_utol(s_edt_cap.edit.text, 10); + if (s_rad_gun.radio.value) { + box.type = BOX_TYPE_GUN; + } + else { + box.type = BOX_TYPE_BULLET; + } + + /* */ + r = register_box((struct box_data *)&box); + if (r == SUCCESS) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪/弹柜资料更新成功!", + SUCCESS, callback); + + /* log */ + record_manager_log(g_passport.mname, L"更新枪/弹柜资料"); +// struct log_manager manager; +// memset(&manager, 0, sizeof(struct log_manager)); +// manager.id = get_log_no(LOG_MANAGER); +// time(&manager.time); +// sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); +// sgi_cpw2u(manager.content, L"更新枪/弹柜资料"); +// sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪/弹资料更新失败!", + REGISTER_FAIL, callback); + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_cap, FORM_CLASS(MODULE_NAME), 230, 139, 160, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_cap.edit.mask = MSK_DIGIT; + s_edt_cap.edit.word_max = 3; + + /* */ + EDIT_CREATE(s_edt_manager, FORM_CLASS(MODULE_NAME), 230, 178, 160, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_code, FORM_CLASS(MODULE_NAME), 498, 100, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_model, FORM_CLASS(MODULE_NAME), 498, 139, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_unit, FORM_CLASS(MODULE_NAME), 498, 178, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + RADIO_CREATE(s_rad_gun, FORM_CLASS(MODULE_NAME), 224, 98, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + RADIO_CREATE(s_rad_bullet, FORM_CLASS(MODULE_NAME), 307, 98, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 654, 162, 108, 47, 1, + "btn-save-u.png", "btn-save-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_bullet.cpp b/src/fm_reg_bullet.cpp new file mode 100644 index 0000000..c75271a --- /dev/null +++ b/src/fm_reg_bullet.cpp @@ -0,0 +1,191 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_bullet + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_bullet; /* */ +static union sgi_object s_edt_bullet_type; /* */ +static union sgi_object s_edt_for_gun; /* */ +static union sgi_object s_edt_amount; /* */ +static union sgi_object s_edt_batch; /* */ +static union sgi_object s_edt_box_no; /* */ +static union sgi_object s_edt_unit; /* */ +static union sgi_object s_btn_save; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {102, 45, 546, 179, {"bullet-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_save_up(struct sgi_button *object) +{ + +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_bullet, FORM_CLASS(MODULE_NAME), 227, 100, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_bullet_type, FORM_CLASS(MODULE_NAME), 499, 100, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_for_gun, FORM_CLASS(MODULE_NAME), 227, 129, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_amount, FORM_CLASS(MODULE_NAME), 499, 129, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_batch, FORM_CLASS(MODULE_NAME), 227, 159, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_box_no, FORM_CLASS(MODULE_NAME), 499, 159, 142, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_unit, FORM_CLASS(MODULE_NAME), 227, 189, 241, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 654, 162, 108, 47, 1, + "btn-save-u.png", "btn-save-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_fpr1_1.cpp b/src/fm_reg_fpr1_1.cpp new file mode 100644 index 0000000..e2fba95 --- /dev/null +++ b/src/fm_reg_fpr1_1.cpp @@ -0,0 +1,195 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_fpr1_1 + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {368, 97, 274, 235, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {108, 120, 234, 129, {"tip-fpr1_1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + s_fpr_fail = 0; + s_fpr_start = 0; + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // printf("check finger press fail.\n"); + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + fpr_module_trigger(FPR_ENROLL_1); + s_fpr_start = 1; + printf("first enroll.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹登记失败!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + printf("fpr result: %d\n", r); + + g_passport.fpr_id = r; + + /* */ + sgi_form_show(&FORM_CLASS(fm_reg_fpr1_2)); + + } + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_fpr1_2.cpp b/src/fm_reg_fpr1_2.cpp new file mode 100644 index 0000000..d502314 --- /dev/null +++ b/src/fm_reg_fpr1_2.cpp @@ -0,0 +1,192 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_fpr1_2 + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {368, 97, 274, 235, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {108, 120, 234, 129, {"tip-fpr1_2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + s_fpr_fail = 1; + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + fpr_module_trigger(FPR_ENROLL_2); + s_fpr_start = 1; + printf("second enroll.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹登记失败!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + printf("fpr result: %d\n", r); + + /* */ + sgi_form_show(&FORM_CLASS(fm_reg_fpr1_3)); + + } + s_fpr_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_fpr1_3.cpp b/src/fm_reg_fpr1_3.cpp new file mode 100644 index 0000000..9ea1344 --- /dev/null +++ b/src/fm_reg_fpr1_3.cpp @@ -0,0 +1,199 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_fpr1_3 + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {368, 97, 274, 235, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {108, 120, 234, 129, {"tip-fpr1_3.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + sgi_form_show(&FORM_CLASS(fm_reg_person)); + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + fpr_module_trigger(FPR_ENROLL_3); + s_fpr_start = 1; + printf("third enroll.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹登记失败!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + printf("fpr result: %d\n", r); + + struct person_data *person = get_person_reg_data(); + if (g_passport.fpr_enroll == 1) { + person->fpr1 = g_passport.fpr_id; + } + else if (g_passport.fpr_enroll == 2) { + person->fpr2 = g_passport.fpr_id; + } + + /* */ + sgi_form_show(&FORM_CLASS(fm_reg_person)); + + } + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_gun.cpp b/src/fm_reg_gun.cpp new file mode 100644 index 0000000..cd2b518 --- /dev/null +++ b/src/fm_reg_gun.cpp @@ -0,0 +1,384 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_gun + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_gun_code; /* */ +static union sgi_object s_edt_lock_code; /* */ +static union sgi_object s_edt_model; /* */ +static union sgi_object s_edt_caliber; /* */ +static union sgi_object s_edt_bullet; /* */ +static union sgi_object s_edt_holder; /* */ +static union sgi_object s_edt_unit; /* */ +static union sgi_object s_edt_stock_date; /* */ +static union sgi_object s_rad_good; /* */ +static union sgi_object s_rad_fault; /* */ +static union sgi_object s_rad_discard; /* */ +static union sgi_object s_rad_lost; /* */ +static union sgi_object s_btn_save; /* */ +static union sgi_object s_btn_del; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {103, 46, 546, 179, {"gun-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *object) +{ + /* 暂停锁监控 */ + pause_lock_monitor(); + + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* */ + if (g_data_update_state == REG_MODIFY) { + s_edt_gun_code.edit.readonly = 1; + + struct gun_data *p = get_gun_reg_data(); + set_object_text_u(&s_edt_gun_code.edit, p->code); + set_object_text_u(&s_edt_model.edit, p->model); + set_object_text_u(&s_edt_caliber.edit, p->caliber); + set_object_text_u(&s_edt_bullet.edit, p->bullet); + set_object_text_u(&s_edt_holder.edit, p->holder); + set_object_text_u(&s_edt_unit.edit, p->unit); + set_object_text_u(&s_edt_stock_date.edit, p->stock_date); + + sgi_sprintf16(s_edt_lock_code.edit.text, L"%d", p->lock_code); + if (p->status == 0) { + s_rad_good.radio.value = 1; + } + else if (p->status == 1) { + s_rad_fault.radio.value = 1; + } + else if (p->status == 2) { + s_rad_discard.radio.value = 1; + } + else { + s_rad_lost.radio.value = 1; + } + + g_data_update_state = REG_UPDATE; + + s_btn_del.button.state &= ~2; + } + else { + s_edt_gun_code.edit.readonly = 0; + set_object_text_u(&s_edt_gun_code.edit, NULL); + set_object_text_u(&s_edt_lock_code.edit, NULL); + set_object_text_u(&s_edt_model.edit, NULL); + set_object_text_u(&s_edt_caliber.edit, NULL); + set_object_text_u(&s_edt_bullet.edit, NULL); + set_object_text_u(&s_edt_holder.edit, NULL); + set_object_text_u(&s_edt_unit.edit, NULL); + set_object_text_u(&s_edt_stock_date.edit, NULL); + s_rad_good.radio.value = 1; + set_object_focus(&s_edt_gun_code); + + s_btn_del.button.state |= 2; + + g_data_update_state = REG_NONE; + } + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + /* 打开锁监控 */ + resume_lock_monitor(); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == ID_EXIST) { + set_object_focus(&s_edt_gun_code); + } + else if (user == APPEND_FAIL) { + set_object_focus(&s_edt_gun_code); + } + else if (user == ID_INVALID) { + set_object_focus(&s_edt_gun_code); + } +} + +static void btn_save_up(struct sgi_button *object) +{ + s32 r; + struct gun_data gun; + + /* 校验并保存数据 */ + if (sgi_len16(s_edt_gun_code.edit.text) == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支编号不能为空!", + ID_INVALID, callback); + return; + } + sgi_cp16(gun.code, s_edt_gun_code.edit.text); + sgi_cp16(gun.model, s_edt_model.edit.text); + sgi_cp16(gun.caliber, s_edt_caliber.edit.text); + sgi_cp16(gun.bullet, s_edt_bullet.edit.text); + sgi_cp16(gun.holder, s_edt_holder.edit.text); + sgi_cp16(gun.unit, s_edt_unit.edit.text); + sgi_cp16(gun.stock_date, s_edt_stock_date.edit.text); + gun.lock_code =sgi_utol(s_edt_lock_code.edit.text, 10); + if (s_rad_good.radio.value) { + gun.status = 0; + } + else if (s_rad_fault.radio.value) { + gun.status = 1; + } + else if (s_rad_discard.radio.value) { + gun.status = 2; + } + else if (s_rad_lost.radio.value) { + gun.status = 3; + } + else { + gun.status = 4; + } + + if (g_data_update_state == REG_UPDATE) { + r = update_gun(&gun); + } + else { + r = register_gun(&gun); + } + + if (r == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支资料更新成功!", + SUCCESS, callback); + + /* log */ + record_manager_log(g_passport.mname, L"更新枪支资料"); +// struct log_manager manager; +// memset(&manager, 0, sizeof(struct log_manager)); +// manager.id = get_log_no(LOG_MANAGER); +// time(&manager.time); +// sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); +// sgi_cpw2u(manager.content, L"更新枪支资料"); +// sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else if (r == ID_EXIST) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支编号已经存在!", + ID_EXIST, callback); + } + else if (r == APPEND_FAIL) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支资料更新失败!", + ID_EXIST, callback); + } +} + + +static void btn_del_up(struct sgi_button *object) +{ + if (object->state & 2) { /* disable */ + return; + } + + struct gun_data *gun = get_gun_reg_data(); + s32 r = delete_gun(gun); + if (r == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支资料删除成功!", + SUCCESS, callback); + + /* log */ + struct log_manager manager; + memset(&manager, 0, sizeof(struct log_manager)); + manager.id = get_log_no(LOG_MANAGER); + time(&manager.time); + sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); + sgi_cpw2u(manager.content, L"删除枪支资料"); + sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"枪支资料删除失败!", + DEL_FAIL, callback); + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_gun_code, FORM_CLASS(MODULE_NAME), 214, 91, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_gun_code.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_lock_code, FORM_CLASS(MODULE_NAME), 474, 91, 136, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_lock_code.edit.mask = MSK_DIGIT; + s_edt_lock_code.edit.word_max = 3; + + /* */ + EDIT_CREATE(s_edt_model, FORM_CLASS(MODULE_NAME), 214, 116, 120, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_model.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_caliber, FORM_CLASS(MODULE_NAME), 474, 116, 136, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_caliber.edit.word_max = 7; + + /* */ + EDIT_CREATE(s_edt_bullet, FORM_CLASS(MODULE_NAME), 214, 141, 156, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_bullet.edit.word_max = 7; + + /* */ + EDIT_CREATE(s_edt_holder, FORM_CLASS(MODULE_NAME), 474, 141, 136, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_holder.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_unit, FORM_CLASS(MODULE_NAME), 214, 165, 156, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_unit.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_stock_date, FORM_CLASS(MODULE_NAME), 474, 165, 136, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_stock_date.edit.word_max = 15; + + /* */ + RADIO_CREATE(s_rad_good, FORM_CLASS(MODULE_NAME), 208, 192, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + RADIO_CREATE(s_rad_fault, FORM_CLASS(MODULE_NAME), 288, 192, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + RADIO_CREATE(s_rad_discard, FORM_CLASS(MODULE_NAME), 365, 192, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + RADIO_CREATE(s_rad_lost, FORM_CLASS(MODULE_NAME), 441, 192, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 654, 176, 110, 45, 1, + "btn-save-u.png", "btn-save-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + BUTTON_CREATE(s_btn_del, FORM_CLASS(MODULE_NAME), 654, 118, 110, 45, 1, + "btn-del-u.png", "btn-del-d.png", "btn-del-e.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_del.button.up = btn_del_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_person.cpp b/src/fm_reg_person.cpp new file mode 100644 index 0000000..152d985 --- /dev/null +++ b/src/fm_reg_person.cpp @@ -0,0 +1,431 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_person + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_name; /* */ +static union sgi_object s_edt_dept; /* */ +static union sgi_object s_edt_gun; /* */ +static union sgi_object s_edt_lock_code; /* */ +static union sgi_object s_edt_card; /* */ +static union sgi_object s_edt_id; /* */ +static union sgi_object s_edt_post; /* */ +static union sgi_object s_edt_gun_code; /* */ +static union sgi_object s_edt_phone; /* */ +static union sgi_object s_edt_sex; /* */ +static union sgi_object s_edt_age; /* */ +static union sgi_object s_btn_photo; /* */ +static union sgi_object s_btn_pwd; /* */ +static union sgi_object s_btn_fpr1; /* */ +static union sgi_object s_btn_fpr2; /* */ +static union sgi_object s_btn_save; /* */ +static union sgi_object s_btn_del; /* */ +static union sgi_object s_chk_ime; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {127, 51, 546, 315, {"person-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *object) +{ + /* 打开指纹模块电源 */ + power_ctrl(1); + + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 输入法是否可见 */ + if (object->ime) { + object->ime->hide = s_chk_ime.check.value; + printf("check-ime value: %d\n", s_chk_ime.check.value); + } + + /* */ + if (g_passport.reg_flag == REG_NEW) { + s_edt_id.edit.readonly = 0; + set_object_text_u(&s_edt_name.edit, NULL); + set_object_text_u(&s_edt_dept.edit, NULL); + set_object_text_u(&s_edt_gun.edit, NULL); + set_object_text_u(&s_edt_lock_code.edit, NULL); + set_object_text_u(&s_edt_card.edit, NULL); + set_object_text_u(&s_edt_id.edit, NULL); + set_object_text_u(&s_edt_post.edit, NULL); + set_object_text_u(&s_edt_gun_code.edit, NULL); + set_object_text_u(&s_edt_phone.edit, NULL); + set_object_text_u(&s_edt_sex.edit, NULL); + set_object_text_u(&s_edt_age.edit, NULL); + + g_passport.reg_flag = REG_MODIFY; + g_data_update_state = REG_NONE; + + s_btn_del.button.state |= 2; + } + else if (g_data_update_state == REG_MODIFY) { + struct person_data *p = get_person_reg_data(); + + s_edt_id.edit.readonly = 1; + set_object_text_u(&s_edt_id.edit, p->uid); + set_object_text_u(&s_edt_name.edit, p->name); + set_object_text_u(&s_edt_dept.edit, p->dept); + set_object_text_u(&s_edt_gun.edit, p->gun); + set_object_text_u(&s_edt_lock_code.edit, p->uid); + set_object_text_u(&s_edt_post.edit, p->post); + set_object_text_u(&s_edt_gun_code.edit, p->gun_code); + set_object_text_u(&s_edt_phone.edit, p->phone); + set_object_text_u(&s_edt_sex.edit, p->sex); + + sgi_sprintf16(s_edt_age.edit.text, L"%d", p->age); + sgi_sprintf16(s_edt_card.edit.text, L"%d", p->idcard); + + g_data_update_state = REG_UPDATE; + + s_btn_del.button.state &= ~2; + } + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + object->ime->hide = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void btn_photo_up(struct sgi_button *object) +{ + sgi_form_show(&FORM_CLASS(fm_reg_photo)); +} + +static void btn_pwd_up(struct sgi_button *object) +{ + sgi_form_show(&FORM_CLASS(fm_reg_pwd)); +} + +static void btn_fpr1_up(struct sgi_button *object) +{ + g_passport.fpr_enroll = 1; + sgi_form_show(&FORM_CLASS(fm_reg_fpr1_1)); +} + +static void btn_fpr2_up(struct sgi_button *object) +{ + g_passport.fpr_enroll = 2; + sgi_form_show(&FORM_CLASS(fm_reg_fpr1_1)); +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == ID_EXIST) { + set_object_focus(&s_edt_id); + } + else if (user == APPEND_FAIL) { + set_object_focus(&s_edt_name); + } + +} + +static void btn_save_up(struct sgi_button *object) +{ + s32 r; + struct person_data *person = get_person_reg_data(); + + /* 校验并保存数据 */ + sgi_cp16(person->uid, s_edt_id.edit.text); + sgi_cp16(person->name, s_edt_name.edit.text); + sgi_cp16(person->dept, s_edt_dept.edit.text); + sgi_cp16(person->post, s_edt_post.edit.text); + sgi_cp16(person->gun, s_edt_gun.edit.text); + sgi_cp16(person->gun_code, s_edt_gun_code.edit.text); + sgi_cp16(person->phone, s_edt_phone.edit.text); + sgi_cp16(person->sex, s_edt_sex.edit.text); + person->age = sgi_utol(s_edt_age.edit.text, 10); + person->lock_code = sgi_utol(s_edt_lock_code.edit.text, 10); + person->idcard = sgi_utol(s_edt_card.edit.text, 10); + + if (g_data_update_state == REG_UPDATE) { + r = update_person((struct person_data_mem *)person); + } + else { + r = register_person((struct person_data_mem *)person); + } + + if (r == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户资料更新成功!", + SUCCESS, callback); + + /* log */ + record_manager_log(g_passport.mname, L"更新人员资料"); +// struct log_manager manager; +// memset(&manager, 0, sizeof(struct log_manager)); +// manager.id = get_log_no(LOG_MANAGER); +// time(&manager.time); +// sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); +// sgi_cpw2u(manager.content, L"更新人员资料"); +// sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else if (r == ID_EXIST) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户编号已经存在!", + ID_EXIST, callback); + } + else if (r == APPEND_FAIL) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户资料更新失败!", + ID_EXIST, callback); + } +} + +static void btn_del_up(struct sgi_button *object) +{ + if (object->state & 2) { /* disable */ + return; + } + + struct person_data *person = get_person_reg_data(); + s32 r = delete_person((struct person_data_mem *)person); + if (r == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户资料删除成功!", + SUCCESS, callback); + + /* log */ + struct log_manager manager; + memset(&manager, 0, sizeof(struct log_manager)); + manager.id = get_log_no(LOG_MANAGER); + time(&manager.time); + sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); + sgi_cpw2u(manager.content, L"删除人员资料"); + sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户资料删除失败!", + DEL_FAIL, callback); + } +} + +static void chk_ime_up(struct sgi_check *object) +{ + if (object->parent->ime) { + object->parent->ime->hide = object->value; + object->parent->redraw = 1; + printf("check value: %d\n", object->value); + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_name, FORM_CLASS(MODULE_NAME), 212, 101, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_name.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_dept, FORM_CLASS(MODULE_NAME), 212, 126, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_dept.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_gun, FORM_CLASS(MODULE_NAME), 246, 152, 142, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_gun.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_lock_code, FORM_CLASS(MODULE_NAME), 246, 178, 142, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_lock_code.edit.mask = MSK_DIGIT; + s_edt_lock_code.edit.word_max = 3; + + /* */ + EDIT_CREATE(s_edt_card, FORM_CLASS(MODULE_NAME), 246, 204, 142, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_card.edit.mask = MSK_DIGIT; + s_edt_card.edit.word_max = 10; + + /* */ + EDIT_CREATE(s_edt_id, FORM_CLASS(MODULE_NAME), 411, 101, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_id.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_post, FORM_CLASS(MODULE_NAME), 411, 126, 122, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_post.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_gun_code, FORM_CLASS(MODULE_NAME), 493, 152, 142, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_gun_code.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_phone, FORM_CLASS(MODULE_NAME), 493, 178, 142, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_phone.edit.mask = MSK_DIGIT; + s_edt_phone.edit.word_max = 15; + + /* */ + EDIT_CREATE(s_edt_sex, FORM_CLASS(MODULE_NAME), 599, 101, 38, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 1); + s_edt_sex.edit.align = DT_CENTER; + s_edt_sex.edit.word_max = 1; + + /* */ + EDIT_CREATE(s_edt_age, FORM_CLASS(MODULE_NAME), 599, 126, 38, 18, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 2); + s_edt_age.edit.align = DT_CENTER; + s_edt_age.edit.mask = MSK_DIGIT; + s_edt_age.edit.word_max = 3; + + /* */ + BUTTON_CREATE(s_btn_photo, FORM_CLASS(MODULE_NAME), 290, 252, 80, 38, 1, + "btn-enter-u.png", "btn-enter-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_photo.button.up = btn_photo_up; + + /* */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 501, 252, 80, 38, 1, + "btn-enter-u.png", "btn-enter-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* */ + BUTTON_CREATE(s_btn_fpr1, FORM_CLASS(MODULE_NAME), 290, 297, 80, 38, 1, + "btn-enter-u.png", "btn-enter-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr1.button.up = btn_fpr1_up; + + /* */ + BUTTON_CREATE(s_btn_fpr2, FORM_CLASS(MODULE_NAME), 501, 297, 80, 38, 1, + "btn-enter-u.png", "btn-enter-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr2.button.up = btn_fpr2_up; + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 409, 378, 110, 45, 1, + "btn-save-u.png", "btn-save-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + BUTTON_CREATE(s_btn_del, FORM_CLASS(MODULE_NAME), 272, 378, 110, 45, 1, + "btn-del-u.png", "btn-del-d.png", "btn-del-e.png", NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_del.button.up = btn_del_up; + + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* */ + CHECK_CREATE(s_chk_ime, FORM_CLASS(MODULE_NAME), 673, 138, 92, 38, 1, + "chk-ime-u.png", "chk-ime-d.png", IMG_OPTIMIZE | IMG_ALPHA); + s_chk_ime.check.up = chk_ime_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_photo.cpp b/src/fm_reg_photo.cpp new file mode 100644 index 0000000..dcc2b32 --- /dev/null +++ b/src/fm_reg_photo.cpp @@ -0,0 +1,158 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_photo + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_photo; /* */ +static union sgi_object s_btn_save; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {251, 47, 298, 256, {"photo-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 240; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_photo_up(struct sgi_button *object) +{ + +} + +static void btn_save_up(struct sgi_button *object) +{ + +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + BUTTON_CREATE(s_btn_photo, FORM_CLASS(MODULE_NAME), 282, 313, 108, 47, 1, + "btn-photo-u.png", "btn-photo-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_photo.button.up = btn_photo_up; + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 407, 313, 180, 47, 1, + "btn-save-u.png", "btn-save-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_pwd.cpp b/src/fm_reg_pwd.cpp new file mode 100644 index 0000000..828aed5 --- /dev/null +++ b/src/fm_reg_pwd.cpp @@ -0,0 +1,191 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_pwd + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_pwd; /* */ +static union sgi_object s_edt_confirm_pwd; /* */ +static union sgi_object s_btn_confirm; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {216, 92, 367, 68, {"pwd-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + s_timer = 240; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == PWD_NOT_MATCH) { + set_object_focus(&s_edt_confirm_pwd); + } + else if (user == PWD_SHORTEST) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *object) +{ + s32 r; + struct person_data *person = get_person_reg_data(); + + /* 检查两次所输入新密码是否一致 */ + if (sgi_ncmp16(s_edt_pwd.edit.text, s_edt_confirm_pwd.edit.text, + COUNTOF(s_edt_pwd.edit.text)) != 0) { + printf("confirm pwd fail.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"两次输入密码不一致!", + PWD_NOT_MATCH, callback); + return; + } + + /* 检查密码长度是否符合要求 */ + if ((r = sgi_len16(s_edt_pwd.edit.text)) < MIN_PWD_LEN) { + printf("pwd is shortest.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"密码长度应大于6个字符!", + PWD_SHORTEST, callback); + return; + } + printf("pwd len: %d\n", r); + + /* 保存密码并提示 */ + sgi_cp16(person->pwd, s_edt_pwd.edit.text); + msgbox(&FORM_CLASS(MODULE_NAME), L"密码已保存,请牢记您的密码!", + SUCCESS, callback); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 390, 98, 189, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_confirm_pwd, FORM_CLASS(MODULE_NAME), 390, 134, 189, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 341, 178, 107, 44, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_reg_unit.cpp b/src/fm_reg_unit.cpp new file mode 100644 index 0000000..4753a22 --- /dev/null +++ b/src/fm_reg_unit.cpp @@ -0,0 +1,237 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_reg_unit + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_name; /* */ +static union sgi_object s_edt_addr; /* */ +static union sgi_object s_edt_dept; /* */ +static union sgi_object s_edt_parent; /* */ +static union sgi_object s_btn_save; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {127, 45, 547, 179, {"unit-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void load_data(void) +{ + struct unit_data *unit; + size_t size; + + /* */ + unit = (struct unit_data *)open_r(DBD(unit), &size); + if (!unit || size != sizeof(struct unit_data)) { + set_object_text_u(&s_edt_name.edit, NULL); + set_object_text_u(&s_edt_addr.edit, NULL); + set_object_text_u(&s_edt_dept.edit, NULL); + set_object_text_u(&s_edt_parent.edit, NULL); + } + else { + set_object_text_u(&s_edt_name.edit, unit->name); + set_object_text_u(&s_edt_addr.edit, unit->addr); + set_object_text_u(&s_edt_dept.edit, unit->dept); + set_object_text_u(&s_edt_parent.edit, unit->parent); + } + + if (unit) { + close_r(unit, size); + } +} + +static void form_enter(struct sgi_form *) +{ + /* */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* */ + load_data(); + + /* */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_register)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == REGISTER_FAIL) { + set_object_focus(&s_edt_name); + } +} + +static void btn_save_up(struct sgi_button *object) +{ + s32 r; + struct unit_data unit; + + /* */ + memset(&unit, 0, sizeof(struct unit_data)); + sgi_cp16(unit.name, s_edt_name.edit.text); + sgi_cp16(unit.addr, s_edt_addr.edit.text); + sgi_cp16(unit.dept, s_edt_dept.edit.text); + sgi_cp16(unit.parent, s_edt_parent.edit.text); + + r = register_unit((struct unit_data *)&unit); + if (r == SUCCESS) { + msgbox(&FORM_CLASS(MODULE_NAME), L"单位资料更新成功!", + SUCCESS, callback); + + /* log */ + record_manager_log(g_passport.mname, L"更新单位资料"); +// struct log_manager manager; +// memset(&manager, 0, sizeof(struct log_manager)); +// manager.id = get_log_no(LOG_MANAGER); +// time(&manager.time); +// sgi_ncp16(manager.name, g_passport.mname, COUNTOF(manager.name)); +// sgi_cpw2u(manager.content, L"更新单位资料"); +// sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"单位资料更新失败!", + REGISTER_FAIL, callback); + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_name, FORM_CLASS(MODULE_NAME), 276, 90, 340, 23, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_addr, FORM_CLASS(MODULE_NAME), 276, 121, 340, 23, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_dept, FORM_CLASS(MODULE_NAME), 276, 152, 340, 23, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_parent, FORM_CLASS(MODULE_NAME), 276, 183, 340, 23, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 679, 183, 84, 36, 1, + "btn-save-s-u.png", "btn-save-s-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_card_manager.cpp b/src/fm_return_card_manager.cpp new file mode 100644 index 0000000..03bdca9 --- /dev/null +++ b/src/fm_return_card_manager.cpp @@ -0,0 +1,188 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_card_manager + +FORM_MODULE(MODULE_NAME); /* 还枪模块,管理员刷卡验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_card_start = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[3] = { + {333, 88, 273, 234, {"card.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; + s_card_start = 0; + card_start(); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_return_fpr_user)); +} + +static void btn_card_up(struct sgi_button *) +{ + +} + +static void btn_pwd_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_return_pwd_user)); +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + s32 card; + + do { + r = card_state(); + if (r == -1) { + card_start(); + } + else if (r == 1) { + card = get_card_id(); + r = search_mid(&g_passport, SR_CARD, card); + if (r == 0) { + g_passport.visit &= MGR_CARD_MASK; + g_passport.visit |= MGR_CARD_VALID; + sgi_form_show(&FORM_CLASS(fm_return_photo_user)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"卡号无对应的用户信息!", + 0, NULL); + card_start(); + } + } + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 600, 50, 200, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.state |= 2; + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_card_user.cpp b/src/fm_return_card_user.cpp new file mode 100644 index 0000000..c0f45f3 --- /dev/null +++ b/src/fm_return_card_user.cpp @@ -0,0 +1,191 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_card_user + +FORM_MODULE(MODULE_NAME); /* 还枪模块,警员刷卡验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_card_start = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {333, 88, 273, 234, {"card.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; + s_card_start = 0; + card_start(); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_return_fpr_user)); +} + +static void btn_card_up(struct sgi_button *) +{ + +} + +static void btn_pwd_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_return_pwd_user)); +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + s32 card; + + do { + r = card_state(); + if (r == -1) { + card_start(); + } + else if (r == 1) { + card = get_card_id(); + r = search_uid(&g_passport, SR_CARD, card); + if (r == 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_CARD_MASK; + g_passport.visit |= USR_CARD_VALID; + sgi_form_show(&FORM_CLASS(fm_return_fpr_manager)); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"卡号无对应的用户信息!", + 0, NULL); + card_start(); + } + } + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.state |= 2; + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_fpr_manager.cpp b/src/fm_return_fpr_manager.cpp new file mode 100644 index 0000000..3df725d --- /dev/null +++ b/src/fm_return_fpr_manager.cpp @@ -0,0 +1,258 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_fpr_manager + +FORM_MODULE(MODULE_NAME); /* 还枪模块,管理员指纹验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {323, 90, 272, 234, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// s_timer = 60; +// } +} + +static void btn_card_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_return_card_manager)); +} + +static void btn_pwd_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_return_pwd_manager)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + //if (!s_fpr_start) { + // break; + //} + + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + play_effect_fpr(); + fpr_module_trigger(FPR_IDENTIFY); + s_fpr_start = 1; + printf("start identify.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无效,请重新采集!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + r = search_mid(&g_passport, SR_FPR, r); + printf("fpr result: %d\n", r); + if (r == 0) { + g_passport.visit &= MGR_FPR_MASK; + g_passport.visit |= MGR_FPR_VALID; + sgi_form_show(&FORM_CLASS(fm_return_photo_user)); + } + else { + s_fpr_fail = 1; + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无对应的用户信息!", + FPR_FAIL, callback); + } + + } + s_fpr_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.state |= 2; + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_fpr_user.cpp b/src/fm_return_fpr_user.cpp new file mode 100644 index 0000000..ba2006f --- /dev/null +++ b/src/fm_return_fpr_user.cpp @@ -0,0 +1,263 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_fpr_user + +FORM_MODULE(MODULE_NAME); /* 还枪模块,警员指纹验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_fpr; /* 指纹按钮 */ +static union sgi_object s_btn_card; /* 刷卡按钮 */ +static union sgi_object s_btn_pwd; /* 密码按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_fpr_start = 0; +static s32 s_fpr_fail = 0; +static s32 s_timer = 0; + +static struct sgi_widget s_widget[5] = { + {288, 18, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {323, 90, 272, 234, {"fpr.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {71, 145, 209, 127, {"tip0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_lbl_time.label.tag = 60; + s_timer = 60; + s_fpr_start = 0; + s_fpr_fail = 0; + +// if (fpr_open() != 0) { +// printf("fpr open fail.\n"); +// } +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static void btn_fpr_up(struct sgi_button *) +{ +// if (!s_fpr_start) { +// fpr_module_trigger(FPR_IDENTIFY); +// s_fpr_start = 1; +// s_timer = 60; +// } +} + +static void btn_card_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_return_card_user)); +} + +static void btn_pwd_up(struct sgi_button *) +{ + /* 取消指纹识别操作 */ + if (s_fpr_start && fpr_get_busy_flag()) { + fpr_set_cancel_flag(); + } + + sgi_form_show(&FORM_CLASS(fm_return_pwd_user)); +} + +static void callback(s32 user) +{ + if (user == FPR_FAIL) { + s_fpr_fail = 0; + } +} + +static s32 form_frame(struct sgi_form *form) +{ + s32 r; + u32 state = 0; + + do { + //if (!s_fpr_start) { + // break; + //} + + if (s_fpr_fail) { + break; + } + + if (!s_fpr_start) { + //if (fpr_check_press_finger(&state) != 0) { + // break; + //} + if (fpr_press_detect() != 0) { + break; + } + + play_effect_fpr(); + fpr_module_trigger(FPR_IDENTIFY); + s_fpr_start = 1; + printf("start identify.\n"); + } + + if (fpr_get_busy_flag()) { + break; + } + + printf("module is not busy.\n"); + if (fpr_get_error_flag()) { + s_fpr_fail = 1; + printf("fpr_get_error_flag is true.\n"); + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无效,请重新采集!", + FPR_FAIL, callback); + } + else { + r = fpr_get_result(); + printf("fpr result: %d\n", r); + r = search_uid(&g_passport, SR_FPR, r); + if (r == 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_FPR_MASK; + g_passport.visit |= USR_FPR_VALID; + time(&g_passport.return_time); + sgi_form_show(&FORM_CLASS(fm_return_fpr_manager)); + } + else { + s_fpr_fail = 1; + msgbox(&FORM_CLASS(MODULE_NAME), L"指纹无对应的用户信息!", + FPR_FAIL, callback); + } + } + s_fpr_start = 0; + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-1.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 24, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 70, 150, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 指纹按钮 */ + BUTTON_CREATE(s_btn_fpr, FORM_CLASS(MODULE_NAME), 201, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-fpr.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_fpr.button.state |= 2; + s_btn_fpr.button.up = btn_fpr_up; + + /* 刷卡按钮 */ + BUTTON_CREATE(s_btn_card, FORM_CLASS(MODULE_NAME), 340, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-card.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_card.button.up = btn_card_up; + + /* 密码验证按钮 */ + BUTTON_CREATE(s_btn_pwd, FORM_CLASS(MODULE_NAME), 480, 336, 134, 105, 1, + "btn-l-u.png", "btn-l-d.png", "btn-l-t.png", "btn-pwd-1.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_pwd.button.up = btn_pwd_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_photo_user.cpp b/src/fm_return_photo_user.cpp new file mode 100644 index 0000000..8f8ef38 --- /dev/null +++ b/src/fm_return_photo_user.cpp @@ -0,0 +1,192 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_photo_user + +FORM_MODULE(MODULE_NAME); /* 还枪模块,警员照片比对 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_lbl_uid; /* 编号标签 */ +static union sgi_object s_lbl_name; /* 姓名标签 */ +static union sgi_object s_lbl_dept; /* 部门标签 */ +static union sgi_object s_lbl_timing; /* 用时标签 */ +static union sgi_object s_pho_sample; /* 照片样本 */ +static union sgi_object s_pho_real; /* 实时照片 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {112, 64, 574, 302, {"photo-3.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + s_timer = 3; + + /* 获取照片样本 */ + s_pho_sample.photo.surface = load_photo(&g_passport, PHO_SAMPLE); + if (s_pho_sample.photo.surface) { + s_pho_sample.photo.redraw = 1; + } + + /* 获取实时照片 */ + s_pho_real.photo.surface = load_photo(&g_passport, PHO_REAL); + if (s_pho_real.photo.surface) { + s_pho_real.photo.redraw = 1; + } + printf("load photo end.\n"); + + /* 为人员信息框赋值 */ + set_object_text_u(&s_lbl_uid.label, g_passport.uid); + set_object_text_u(&s_lbl_name.label, g_passport.name); + set_object_text_u(&s_lbl_dept.label, g_passport.dept); + //set_object_text_u(&s_lbl_dept.label, g_passport.dept); +} + +static void form_exit(struct sgi_form *) +{ + printf("unload photo.\n"); + unload_photo(&s_pho_sample.photo); + unload_photo(&s_pho_real.photo); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + sgi_form_show(&FORM_CLASS(fm_return_unlock)); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_return_unlock)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号 */ + LABEL_CREATE(s_lbl_uid, FORM_CLASS(MODULE_NAME), 546, 92, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 姓名 */ + LABEL_CREATE(s_lbl_name, FORM_CLASS(MODULE_NAME), 546, 134, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 部门 */ + LABEL_CREATE(s_lbl_dept, FORM_CLASS(MODULE_NAME), 546, 176, 120, 25, 1, + "jht.ttf", 20, text_cl); + + /* 用时 */ + LABEL_CREATE(s_lbl_timing, FORM_CLASS(MODULE_NAME), 588, 220, 35, 40, 1, + "jht.ttf", 20, text_cl); + s_lbl_timing.label.align = DT_CENTER; + //set_object_text_w(&s_lbl_timing.label, L"24"); + + /* 照片样本 */ + PHOTO_CREATE(s_pho_sample, FORM_CLASS(MODULE_NAME), 135, 87, 158, 178, 1); + + /* 实时照片 */ + PHOTO_CREATE(s_pho_real, FORM_CLASS(MODULE_NAME), 307, 87, 158, 178, 1); + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_pwd_manager.cpp b/src/fm_return_pwd_manager.cpp new file mode 100644 index 0000000..e36ceb6 --- /dev/null +++ b/src/fm_return_pwd_manager.cpp @@ -0,0 +1,183 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_pwd_manager + +FORM_MODULE(MODULE_NAME); /* 还枪模块,管理员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {165, 59, 377, 95, {"pwd-2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; + s_pwd_retries = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_manager_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + g_passport.visit &= MGR_PWD_MASK; + g_passport.visit |= MGR_PWD_VALID; + sgi_form_show(&FORM_CLASS(fm_return_photo_user)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 86, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 126, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_pwd_user.cpp b/src/fm_return_pwd_user.cpp new file mode 100644 index 0000000..f6c81af --- /dev/null +++ b/src/fm_return_pwd_user.cpp @@ -0,0 +1,185 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_pwd_user + +FORM_MODULE(MODULE_NAME); /* 还枪模块,警员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {188, 58, 353, 106, {"pwd-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; + s_pwd_retries = 0; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + s32 r = verify_user_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + g_passport.visit |= VALID_PASSPORT; + g_passport.visit &= USR_PWD_MASK; + g_passport.visit |= USR_PWD_VALID; + sgi_form_show(&FORM_CLASS(fm_return_fpr_manager)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 83, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 123, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_return_unlock.cpp b/src/fm_return_unlock.cpp new file mode 100644 index 0000000..4685431 --- /dev/null +++ b/src/fm_return_unlock.cpp @@ -0,0 +1,280 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_return_unlock + +FORM_MODULE(MODULE_NAME); /* 还枪模块,枪柜开锁 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_box; /* 枪柜 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_cell s_box_cell[BOX_NUMS] = { + CELL(15,11,61,40),CELL(79,11,61,40),CELL(143,11,61,40), + CELL(205,11,61,40),CELL(268,11,61,40),CELL(332,11,61,40), + CELL(395,11,61,40),CELL(457,11,61,40),CELL(520,11,61,40), + CELL(584,11,61,40), + + CELL(15,54,61,40),CELL(79,54,61,40),CELL(143,54,61,40), + CELL(205,54,61,40),CELL(268,54,61,40),CELL(332,54,61,40), + CELL(395,54,61,40),CELL(457,54,61,40),CELL(520,54,61,40), + CELL(584,54,61,40), + + CELL(15,96,61,40),CELL(79,96,61,40),CELL(143,96,61,40), + CELL(205,96,61,40),CELL(268,96,61,40),CELL(332,96,61,40), + CELL(395,96,61,40),CELL(457,96,61,40),CELL(520,96,61,40), + CELL(584,96,61,40), + + CELL(15,138,102,77),CELL(121,138,102,77),CELL(227,138,102,77), + CELL(331,138,102,77),CELL(438,138,102,77),CELL(541,138,102,77), + + CELL(15,218,102,77),CELL(121,218,102,77),CELL(227,218,102,77), + CELL(331,218,102,77),CELL(438,218,102,77),CELL(541,218,102,77), +}; + +static struct sgi_widget s_widget[] = { + {69, 55, 658, 308, {"photo-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + u32 i; + struct box_info *info = get_box_info(); + + /* 暂停锁监控 */ + pause_lock_monitor(); + + /* */ + for (i = 0; i < BOX_NUMS; ++i) { + s_box.box.cell[i].state = 0; + if ((info[i].state & 3) == 1) { + s_box.box.cell[i].tag = 3; + } + else if ((info[i].state & 3) == 3) { + s_box.box.cell[i].tag = 1; + } + + printf("info[%d]: %d\n", i, info[i].state); + } + + /* only show current user's borrow */ + u8 *user = get_return_info(g_passport.uid); + for (i = 0; i < BOX_NUMS; ++i) { + printf("user[%d]: %d\n", i, user[i]); + if (!user[i] && s_box.box.cell[i].tag == 1) { + s_box.box.cell[i].tag = 3; + } + } + + s_timer = 600; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_main.button.up(&s_btn_main.button); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + int i; + u32 cells[4] = {0}; + struct box_info *info = get_box_info(); + + int has = 0; + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + has = 1; + break; + } + } + + if (!has) { + return; + } + + /* 查询借枪信息 */ + if (!search_borrow_info(&g_passport)) { + msgbox(&FORM_CLASS(MODULE_NAME), L"无此用户的借枪信息!", 0, NULL); + return; + } + + /* 登记还枪信息 */ + for (i = 0; i < BOX_NUMS; ++i) { + cells[i / 32] |= (s_box.box.cell[i].state & 1) << (i % 32); + } + if (enroll_return(&g_passport, cells) != 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"登记还枪信息失败!", 0, NULL); + return; + } + + /* 记录还枪日志 */ + //struct log_borrow back; + int nums = 0; + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + record_return_log(&g_passport, &info[i]); + nums++; +// memset(&back, 0, sizeof(struct log_borrow)); +// back.id = get_log_no(LOG_RETURN); +// time(&back.time); +// sgi_ncp16(back.name, g_passport.name, +// COUNTOF(back.name)); +// sgi_ncp16(back.gun_type, info[i].gun_model, +// COUNTOF(back.gun_type)); +// sgi_ncp16(back.gun_code, info[i].gun_code, +// COUNTOF(back.gun_code)); +// sgi_append_log(DBL(back), &back, +// sizeof(struct log_borrow)); + } + } + + /* 记录上报数据 */ + recorcd_return_report(&g_passport, 0, nums); + + /* 打开枪柜门 */ + authorize_open_door(); + + /* 打开对应枪锁 */ + for (i = 0; i < BOX_NUMS; ++i) { + if (s_box.box.cell[i].state & 1) { + if (i2c_comm_unlock(s_box.box.cell_addr[i]) == 0) { + set_lock_list(s_box.box.cell_addr[i]); + SDL_Delay(2000); + } + } + } + + msgbox(&FORM_CLASS(MODULE_NAME), L"请在规定的时间内归还枪械并关闭柜门!", + 0, callback); +} + +static void btn_back_up(struct sgi_button *) +{ + +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 32, 150, 22, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 枪柜表格 */ + BOX_CREATE(s_box, FORM_CLASS(MODULE_NAME), 69, 55, 658, 308, 1, + "jht.ttf", 20, color, "box-2.png", "box-4.png", "box-0.png", + "box-3.png", IMG_OPTIMIZE | IMG_ALPHA, s_box_cell); + s_box.box.cell_addr = g_box_addr; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 346, 383, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_safecheck.cpp b/src/fm_safecheck.cpp new file mode 100644 index 0000000..273725b --- /dev/null +++ b/src/fm_safecheck.cpp @@ -0,0 +1,316 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_safecheck + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_power; /* */ +static union sgi_object s_lbl_door; /* */ +static union sgi_object s_lbl_lock; /* */ +static union sgi_object s_lbl_fpr; /* */ +static union sgi_object s_lbl_net; /* */ + +static struct sgi_widget s_widget[3] = { + {134, 22, 332, 262, {"safecheck.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 s_check_step = 0; + +static void form_enter(struct sgi_form *) +{ + pause_all_monitor(); + + set_object_text_u(&s_lbl_power.label, NULL); + set_object_text_u(&s_lbl_door.label, NULL); + set_object_text_u(&s_lbl_lock.label, NULL); + set_object_text_u(&s_lbl_fpr.label, NULL); + set_object_text_u(&s_lbl_net.label, NULL); +} + +static void form_exit(struct sgi_form *) +{ + resume_all_monitor(); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 power_check(void) +{ + static s32 count = 0; + static s32 flags = 0; + s32 s; + + s = get_pw_jc(); + if (s != -1) { + flags <<= 1; + flags |= (s & 1); + } + count++; + + if (count >= 3) { + if ((flags & 7) == 0) { + set_object_text_w(&s_lbl_power.label, L"备用电源供电"); + s_lbl_power.label.redraw = 1; + } + else { + set_object_text_w(&s_lbl_power.label, L"市电供电"); + s_lbl_power.label.redraw = 1; + } + return 1; + } + + return 0; +} + +static s32 door_check(void) +{ + static s32 count = 0; + static s32 flags = 0; + static s32 qzw1 = 0; + static s32 qzw2 = 0; + s32 s; + + s = get_door_fb(); + if (s != -1) { + //flags <<= 1; + flags |= (s & 1); + } + + s = get_qwz1(); + if (s != -1) { + //qzw1 <<= 1; + qzw1 |= (s & 1); + } + + s = get_qwz2(); + if (s != -1) { + //qzw1 <<= 1; + qzw2 |= (s & 1); + } + + count++; + + if (count >= 3) { + if ((flags & 1) == 0 || (qzw1 & 1) == 0 || (qzw2 & 1) == 0) { + set_object_text_w(&s_lbl_door.label, L"柜门锁开启"); + s_lbl_door.label.redraw = 1; + } + else { + set_object_text_w(&s_lbl_door.label, L"柜门锁关闭"); + s_lbl_door.label.redraw = 1; + } + return 1; + } + + return 0; +} + +static s32 lock_check(void) +{ + s32 i; + s32 err = 0; + s32 ok = 0; + wchar_t buf[64]; + + struct box_info *info = get_box_info(); + for (i = 0; i < BOX_NUMS; ++i) { + if ((info[i].state & 1) == 0) { + continue; + } + + /* */ + if (i2c_comm_update_state(g_box_addr[i]) != 0) { + err++; + } + else { + ok++; + } + + SDL_Delay(200); + } + + swprintf(buf, COUNTOF(buf), L"通讯正常[%d], 通讯失败[%d]", ok, err); + + set_object_text_w(&s_lbl_lock.label, buf); + + return 1; +} + +static s32 fpr_check(void) +{ + u32 ver; + wchar_t buf[64]; + + if (fpr_get_ver(&ver) != 0) { + swprintf(buf, COUNTOF(buf), L"模块自检失败"); + } + else { + swprintf(buf, COUNTOF(buf), L"模块工作正常,版本: %d", ver); + } + + set_object_text_w(&s_lbl_fpr.label, buf); + + return 1; +} + +static s32 net_check(void) +{ + u32 t = SDL_GetTicks() + 3000; + + create_heartbeat_packet(); + + do { + if (get_net_link_status()) { + break; + } + SDL_Delay(500); + } while (TIME_BEFORE(SDL_GetTicks(), t)); + + if (get_net_link_status()) { + set_object_text_w(&s_lbl_net.label, L"网络已连接"); + } + else { + set_object_text_w(&s_lbl_net.label, L"网络未连接"); + } + + return 1; +} + +static s32 form_frame(struct sgi_form *form) +{ + static u32 cycle = 0; + + /* per 1s check device */ + if (TIME_AFTER(SDL_GetTicks(), cycle)) { + + switch (s_check_step) { + case 0: + set_object_text_w(&s_lbl_power.label, L"正在检测..."); + s_lbl_power.label.redraw = 1; + if (power_check()) { + s_check_step++; + } + break; + + case 1: + set_object_text_w(&s_lbl_door.label, L"正在检测..."); + s_lbl_door.label.redraw = 1; + if (door_check()) { + s_check_step++; + } + break; + + case 2: + set_object_text_w(&s_lbl_lock.label, L"正在检测..."); + s_lbl_lock.label.redraw = 1; + if (lock_check()) { + s_check_step++; + } + break; + + case 3: + set_object_text_w(&s_lbl_fpr.label, L"正在检测..."); + s_lbl_fpr.label.redraw = 1; + if (fpr_check()) { + s_check_step++; + } + break; + + case 4: + set_object_text_w(&s_lbl_net.label, L"正在检测..."); + s_lbl_net.label.redraw = 1; + if (net_check()) { + s_check_step++; + } + break; + + case 5: + SDL_Delay(3000); + s_check_step++; + break; + + default: + break; + + } + cycle = SDL_GetTicks() + 1000; + } + + sgi_form_frame_default(form); + + if (s_check_step > 5) { + sgi_form_show(&FORM_CLASS(fm_main)); + } + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + LABEL_CREATE(s_lbl_power, FORM_CLASS(MODULE_NAME), 320, 98, 364, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_door, FORM_CLASS(MODULE_NAME), 320, 139, 364, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_lock, FORM_CLASS(MODULE_NAME), 320, 180, 364, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_fpr, FORM_CLASS(MODULE_NAME), 320, 219, 364, 25, 1, + "jht.ttf", 24, color); + + LABEL_CREATE(s_lbl_net, FORM_CLASS(MODULE_NAME), 320, 260, 364, 25, 1, + "jht.ttf", 24, color); + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_stat_box.cpp b/src/fm_stat_box.cpp new file mode 100644 index 0000000..0d7b4e0 --- /dev/null +++ b/src/fm_stat_box.cpp @@ -0,0 +1,191 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_stat_box + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_cap; /* */ +static union sgi_object s_edt_manager; /* */ +static union sgi_object s_edt_code; /* */ +static union sgi_object s_edt_specs; /* */ +static union sgi_object s_edt_dept; /* */ +static union sgi_object s_rad_gun; /* */ +static union sgi_object s_rad_bullet; /* */ +static union sgi_object s_btn_edit; /* 返回按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {127, 100, 547, 179, {"box-info.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + //register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_edit_up(struct sgi_button *object) +{ + +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_cap, FORM_CLASS(MODULE_NAME), 256, 194, 159, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_manager, FORM_CLASS(MODULE_NAME), 256, 233, 159, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_code, FORM_CLASS(MODULE_NAME), 524, 156, 122, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_specs, FORM_CLASS(MODULE_NAME), 524, 194, 122, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_dept, FORM_CLASS(MODULE_NAME), 524, 233, 122, 16, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + RADIO_CREATE(s_rad_gun, FORM_CLASS(MODULE_NAME), 250, 153, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + RADIO_CREATE(s_rad_bullet, FORM_CLASS(MODULE_NAME), 333, 153, 33, 23, 1, + "rad-sel-u.png", "rad-sel-d.png", IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + BUTTON_CREATE(s_btn_edit, FORM_CLASS(MODULE_NAME), 367, 290, 80, 38, 1, + "btn-edit-u.png", "btn-edit-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_edit.button.up = btn_edit_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_stat_bullet.cpp b/src/fm_stat_bullet.cpp new file mode 100644 index 0000000..d2b90ad --- /dev/null +++ b/src/fm_stat_bullet.cpp @@ -0,0 +1,168 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_stat_bullet + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {74, 43, 654, 333, {"bullet-info.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + //register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + +} + +static void btn_next_up(struct sgi_button *) +{ + +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 318, 395, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 409, 395, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_stat_gun.cpp b/src/fm_stat_gun.cpp new file mode 100644 index 0000000..be0ba4e --- /dev/null +++ b/src/fm_stat_gun.cpp @@ -0,0 +1,374 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_stat_gun + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct gun_data *s_grid_data = NULL; + +//static struct sgi_widget s_widget[] = { +// {74, 43, 654, 333, {"gun-info.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, +// {0, 0, 0, 0, {NULL, 0, NULL}}, +//}; +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + struct gun_data *p; + s32 offset; + s32 read_count; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + p = s_grid_data + offset; + read_count = s_record_count - offset; + for (i = 0; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_ncp16(object->cells[index].string, p->code, + COUNTOF(p->code)); + break; + + case 1: /* column 1 */ + sgi_ncp16(object->cells[index].string, p->model, + COUNTOF(p->model)); + break; + + case 2: /* column 2 */ + sgi_sprintf16(object->cells[index].string, + L"%d", p->lock_code); + break; + + case 3: /* column 3 */ + sgi_ncp16(object->cells[index].string, p->holder, + COUNTOF(p->holder)); + break; + + case 4: /* column 4 */ + sgi_ncp16(object->cells[index].string, p->bullet, + COUNTOF(p->bullet)); + break; + + default: + break; + + } + } + + if (--read_count <= 0) { + break; + } + p++; + } + + /* 剩余行清零 */ + for (i += 1; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 6; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 40; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 136; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 231; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 326; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 423; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 5: /* column 5 */ + object->cells[index].type = GRID_BUTTON; + object->cells[index].x = object->x + 519; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct gun_data *)open_r(DBD(gun), &s_data_size); + s_record_count = s_data_size / sizeof(struct gun_data); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_r(s_grid_data, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void edit_button_up(struct sgi_grid *, s32 row) +{ + s32 index = s_page * s_grid.grid.row + row; + if (index >= s_record_count) { + return; + } + + struct gun_data *ps = s_grid_data + index; + struct gun_data *pd = get_gun_reg_data(); + g_data_update_state = REG_MODIFY; + memcpy(pd, ps, sizeof(struct gun_data)); + + sgi_form_show(&FORM_CLASS(fm_reg_gun)); +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 74, 43, 654, 333, 1, + "jht.ttf", 20, color, "gun-info.png", "grid-edit.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.up = edit_button_up; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 318, 395, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 409, 395, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_stat_person.cpp b/src/fm_stat_person.cpp new file mode 100644 index 0000000..eb1b9cc --- /dev/null +++ b/src/fm_stat_person.cpp @@ -0,0 +1,380 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_stat_person + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct person_data *s_person = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + struct person_data *p; + s32 offset; + s32 read_count; + u16 level[5][8] = { + {(u16)L'普',(u16)L'通',(u16)L'用',(u16)L'户'}, + {(u16)L'管',(u16)L'理',(u16)L'员'}, + {(u16)L'监',(u16)L'督',(u16)L'员',(u16)L'户'}, + {(u16)L'高',(u16)L'级',(u16)L'监',(u16)L'督',(u16)L'员'}, + {(u16)L'未',(u16)L'知'}, + }; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_person || offset > s_record_count) { + return; + } + + p = s_person + offset; + read_count = s_record_count - offset; + for (i = 0; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + sgi_ncp16(object->cells[index].string, p->uid, + COUNTOF(p->uid)); + break; + + case 1: /* column 1 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 2: /* column 2 */ + sgi_ncp16(object->cells[index].string, p->dept, + COUNTOF(p->dept)); + break; + + case 3: /* column 3 */ + sgi_ncp16(object->cells[index].string, p->post, + COUNTOF(p->post)); + break; + + case 4: /* column 4 */ + printf("level: %d\n", p->level); + if (p->level < 5) { + sgi_ncp16(object->cells[index].string, + level[p->level], COUNTOF(level[0])); + } + break; + + default: + break; + + } + } + + if (--read_count <= 0) { + break; + } + p++; + } + + /* 剩余行清零 */ + for (i += 1; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 62; + const s32 row_h = 26; + + /* */ + object->col = 6; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 40; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 136; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 231; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 326; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 423; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + case 5: /* column 5 */ + object->cells[index].type = GRID_BUTTON; + object->cells[index].x = object->x + 519; + object->cells[index].y = y0; + object->cells[index].w = 95; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* 初始化所有参数 */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_person = (struct person_data *)open_r(DBD(person), &s_data_size); + s_record_count = s_data_size / sizeof(struct person_data); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_person) { + close_r(s_person, s_data_size); + } +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void edit_button_up(struct sgi_grid *, s32 row) +{ + s32 index = s_page * s_grid.grid.row + row; + if (index >= s_record_count) { + return; + } + + struct person_data *ps = s_person + index; + struct person_data *pd = get_person_reg_data(); + g_data_update_state = REG_MODIFY; + memcpy(pd, ps, sizeof(struct person_data)); + + sgi_form_show(&FORM_CLASS(fm_reg_person)); +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 74, 43, 654, 333, 1, + "jht.ttf", 20, color, "person-info.png", "grid-edit.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_grid.grid.up = edit_button_up; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 318, 395, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 409, 395, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_stat_unit.cpp b/src/fm_stat_unit.cpp new file mode 100644 index 0000000..be9099c --- /dev/null +++ b/src/fm_stat_unit.cpp @@ -0,0 +1,176 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_stat_unit + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_name; /* */ +static union sgi_object s_edt_addr; /* */ +static union sgi_object s_edt_dept; /* */ +static union sgi_object s_edt_parent; /* */ +static union sgi_object s_btn_edit; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {126, 101, 547, 179, {"unit-reg.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + //register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_info_stat)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + +} + +static void btn_edit_up(struct sgi_button *object) +{ + +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_name, FORM_CLASS(MODULE_NAME), 279, 147, 340, 19, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_addr, FORM_CLASS(MODULE_NAME), 279, 179, 340, 19, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_dept, FORM_CLASS(MODULE_NAME), 279, 209, 340, 19, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + EDIT_CREATE(s_edt_parent, FORM_CLASS(MODULE_NAME), 279, 240, 340, 19, 1, + "jht.ttf", 18, text_cl, "cursor-1.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* */ + BUTTON_CREATE(s_btn_edit, FORM_CLASS(MODULE_NAME), 359, 289, 80, 38, 1, + "btn-edit-u.png", "btn-edit-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_edit.button.up = btn_edit_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_system.cpp b/src/fm_system.cpp new file mode 100644 index 0000000..8a0ec32 --- /dev/null +++ b/src/fm_system.cpp @@ -0,0 +1,157 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_system + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_code; /* 枪柜编号 */ +static union sgi_object s_btn_db; /* 数据库设置 */ +static union sgi_object s_btn_box; /* 枪柜参数设置 */ +static union sgi_object s_btn_sms; /* 短信功能设置 */ +static union sgi_object s_btn_dt; /* 系统日期时间设置 */ +static union sgi_object s_btn_remote; /* 远程控制设置 */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {288, 20, 225, 54, {"title-0.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {211, 454, 380, 16, {"title-1.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_db_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_download)); +} + +static void btn_box_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_mon_setting)); +} + +static void btn_sms_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_dt_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_timing)); +} + +static void btn_remote_up(struct sgi_button *) +{ + //sgi_form_show(&FORM_CLASS(fm_chpwd)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 单位编号 */ + LABEL_CREATE(s_lbl_code, FORM_CLASS(MODULE_NAME), 600, 45, 200, 25, 1, + "jht.ttf", 18, color); + swprintf(buf, sizeof(buf), L"枪弹柜编号: A%03d", 1); + set_object_text_w(&s_lbl_code.label, buf); + + /* 数据库设置 */ + BUTTON_CREATE(s_btn_db, FORM_CLASS(MODULE_NAME), 409, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-dbset.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_db.button.up = btn_db_up; + + /* 枪柜参数设置 */ + BUTTON_CREATE(s_btn_box, FORM_CLASS(MODULE_NAME), 200, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-boxset.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_box.button.up = btn_box_up; + + /* 短信功能设置 */ + BUTTON_CREATE(s_btn_sms, FORM_CLASS(MODULE_NAME), 340, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-smsset.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_sms.button.up = btn_sms_up; + + /* 系统日期时间设置 */ + BUTTON_CREATE(s_btn_dt, FORM_CLASS(MODULE_NAME), 480, 245, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-dtset.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_dt.button.up = btn_dt_up; + + /* 远程控制设置 */ + BUTTON_CREATE(s_btn_remote, FORM_CLASS(MODULE_NAME), 266, 136, 122, 96, 1, + "btn-m-u.png", "btn-m-d.png", "btn-m-t.png", "btn-remote-set.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_remote.button.up = btn_remote_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_timing.cpp b/src/fm_timing.cpp new file mode 100644 index 0000000..4c48aef --- /dev/null +++ b/src/fm_timing.cpp @@ -0,0 +1,327 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_timing + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 时间标签 */ +static union sgi_object s_edt_hour; /* */ +static union sgi_object s_edt_minute; /* */ +static union sgi_object s_edt_year; /* */ +static union sgi_object s_edt_month; /* */ +static union sgi_object s_edt_day; /* */ +static union sgi_object s_btn_network; /* */ +static union sgi_object s_btn_confirm; /* */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static struct sgi_widget s_widget[] = { + {94, 38, 546, 196, {"timing.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + /* 清空输入框 */ + set_object_text_u(&s_edt_hour.edit, NULL); + set_object_text_u(&s_edt_minute.edit, NULL); + set_object_text_u(&s_edt_year.edit, NULL); + set_object_text_u(&s_edt_month.edit, NULL); + set_object_text_u(&s_edt_day.edit, NULL); + set_object_focus(&s_edt_hour); + + s_timer = 240; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + //s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_system)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +#define HOUR_INVALID 1 +#define MINUTE_INVALID 2 +#define YEAR_INVALID 3 +#define MONTH_INVALID 4 +#define DAY_INVALID 5 +#define TIME_INVALID 6 + +static void callback(s32 user) +{ + if (user == SUCCESS) { + s_btn_back.button.up(&s_btn_back.button); + } + else if (user == HOUR_INVALID) { + set_object_focus(&s_edt_hour); + } + else if (user == MINUTE_INVALID) { + set_object_focus(&s_edt_minute); + } + else if (user == YEAR_INVALID) { + set_object_focus(&s_edt_year); + } + else if (user == MONTH_INVALID) { + set_object_focus(&s_edt_month); + } + else if (user == DAY_INVALID) { + set_object_focus(&s_edt_day); + } + else if (user == TIME_INVALID) { + + } +} + +static void btn_network_up(struct sgi_button *) +{ + u32 t = SDL_GetTicks() + 5000; + s32 status; + + create_time_adjust_packet(); + do { + if ((status = get_time_adjust_status())) { + break; + } + SDL_Delay(500); + } while (TIME_BEFORE(SDL_GetTicks(), t)); + + if (status) { + msgbox(&FORM_CLASS(MODULE_NAME), L"校时成功!", 0, NULL); + } + else { + msgbox(&FORM_CLASS(MODULE_NAME), L"校时失败!", 0, NULL); + } +} + +static void btn_confirm_up(struct sgi_button *object) +{ + s32 r; + s32 temp; + struct tm mytm; + time_t mytime; + + /* 检查小时 */ + memset(&mytm, 0, sizeof(struct tm)); + if (sgi_len16(s_edt_hour.edit.text) == 0) { + set_object_focus(&s_edt_hour); + } + temp = sgi_utol(s_edt_hour.edit.text, 10); + if (temp < 0 || temp > 23) { + msgbox(&FORM_CLASS(MODULE_NAME), L"小时数据无效(0-23)!", + HOUR_INVALID, callback); + return; + } + mytm.tm_hour = temp; + + /* 检查分钟 */ + if (sgi_len16(s_edt_minute.edit.text) == 0) { + set_object_focus(&s_edt_minute); + } + temp = sgi_utol(s_edt_minute.edit.text, 10); + if (temp < 0 || temp > 59) { + msgbox(&FORM_CLASS(MODULE_NAME), L"分钟数据无效(0-59)!", + MINUTE_INVALID, callback); + return; + } + mytm.tm_min = temp; + + /* 检查年份 */ + if (sgi_len16(s_edt_year.edit.text) == 0) { + set_object_focus(&s_edt_year); + } + temp = sgi_utol(s_edt_year.edit.text, 10); + if (temp < 1970 || temp > 3000) { + msgbox(&FORM_CLASS(MODULE_NAME), L"年份数据无效(1970-3000)!", + YEAR_INVALID, callback); + return; + } + mytm.tm_year = temp - 1900; + + /* 检查月份 */ + if (sgi_len16(s_edt_month.edit.text) == 0) { + set_object_focus(&s_edt_month); + } + temp = sgi_utol(s_edt_month.edit.text, 10); + if (temp < 1 || temp > 12) { + msgbox(&FORM_CLASS(MODULE_NAME), L"月份数据无效(1-12)!", + MONTH_INVALID, callback); + return; + } + mytm.tm_mon = temp - 1; + + /* 检查日期 */ + if (sgi_len16(s_edt_day.edit.text) == 0) { + set_object_focus(&s_edt_day); + } + temp = sgi_utol(s_edt_day.edit.text, 10); + if (temp < 1 || temp > 31) { + msgbox(&FORM_CLASS(MODULE_NAME), L"月份数据无效(1-31)!", + DAY_INVALID, callback); + return; + } + mytm.tm_mday = temp; + + /* 设置日期时间 */ + mytime = mktime(&mytm); + if (mytime == -1) { + msgbox(&FORM_CLASS(MODULE_NAME), L"校时失败!", + TIME_INVALID, callback); + return; + } + + if (stime(&mytime) != 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"校时失败!", + TIME_INVALID, callback); + return; + } + + /* 写入RTC */ + system("hwclock --systohc"); + + /* 保存密码并提示 */ + msgbox(&FORM_CLASS(MODULE_NAME), L"校时成功!", + SUCCESS, callback); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + //s_lbl_time.label.frame = lbl_time_frame; + + /* */ + EDIT_CREATE(s_edt_hour, FORM_CLASS(MODULE_NAME), 281, 103, 61, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_hour.edit.mask = MSK_DIGIT; + + /* */ + EDIT_CREATE(s_edt_minute, FORM_CLASS(MODULE_NAME), 368, 103, 60, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_minute.edit.mask = MSK_DIGIT; + + /* */ + EDIT_CREATE(s_edt_year, FORM_CLASS(MODULE_NAME), 280, 164, 79, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_year.edit.mask = MSK_DIGIT; + + /* */ + EDIT_CREATE(s_edt_month, FORM_CLASS(MODULE_NAME), 391, 164, 41, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_month.edit.mask = MSK_DIGIT; + + /* */ + EDIT_CREATE(s_edt_day, FORM_CLASS(MODULE_NAME), 463, 164, 41, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_day.edit.mask = MSK_DIGIT; + + /* */ + BUTTON_CREATE(s_btn_network, FORM_CLASS(MODULE_NAME), 652, 123, 107, 44, 1, + "btn-net-u.png", "btn-net-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_network.button.up = btn_network_up; + + /* */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 652, 183, 107, 44, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_unlock.cpp b/src/fm_unlock.cpp new file mode 100644 index 0000000..7073383 --- /dev/null +++ b/src/fm_unlock.cpp @@ -0,0 +1,149 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_unlock + +FORM_MODULE(MODULE_NAME); /* 权限管理模块 */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_btn_unlock; /* */ +static union sgi_object s_btn_cancel; /* */ +static union sgi_object s_btn_back; /* 返回 */ +static union sgi_object s_btn_main; /* 首页 */ + +static struct sgi_widget s_widget[3] = { + {127, 113, 547, 179, {"unlock.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 暂停锁监控 */ + pause_lock_monitor(); +} + +static void form_exit(struct sgi_form *) +{ + //alarm_ctrl(0); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_unlock_up(struct sgi_button *) +{ + int i; + + // test + //alarm_ctrl(1); + door_ctrl(DOOR_OPEN); + + /* unlock all */ + for (i = 0; i < BOX_NUMS; ++i) { + if (i2c_comm_unlock(g_box_addr[i]) == 0) { + SDL_Delay(2000); + } + } + + /* log */ +// struct log_alarm log; +// memset(&log, 0, sizeof(struct log_alarm)); +// log.id = get_log_no(LOG_ALARM); +// time(&log.time); +// sgi_cpw2u(log.content, L"紧急开锁"); +// sgi_append_log(DBL(alarm), &log, sizeof(struct log_alarm)); + record_alarm_log(L"紧急开锁"); + + SDL_Delay(100); + door_ctrl(DOOR_CLOSE); +} + +static void btn_cancel_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_menu)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-0.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* */ + BUTTON_CREATE(s_btn_unlock, FORM_CLASS(MODULE_NAME), 282, 217, 107, 44, 1, + "btn-unlock-u.png", "btn-unlock-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_unlock.button.up = btn_unlock_up; + + /* */ + BUTTON_CREATE(s_btn_cancel, FORM_CLASS(MODULE_NAME), 408, 217, 107, 44, 1, + "btn-cancel-u.png", "btn-cancel-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_cancel.button.up = btn_cancel_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 109, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 611, 350, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_unlock_pwd.cpp b/src/fm_unlock_pwd.cpp new file mode 100644 index 0000000..1f48989 --- /dev/null +++ b/src/fm_unlock_pwd.cpp @@ -0,0 +1,188 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_unlock_pwd + +FORM_MODULE(MODULE_NAME); /* 取枪模块,警员密码验证 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_edt_uid; /* 用户编号 */ +static union sgi_object s_edt_pwd; /* 密码输入框 */ +static union sgi_object s_btn_confirm; /* 确认按钮 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_pwd_retries = 0; + +static struct sgi_widget s_widget[3] = { + {165, 59, 377, 95, {"pwd-2.png", IMG_OPTIMIZE | IMG_ALPHA, NULL}}, + {0, 0, 0, 0, {NULL, 0, NULL}}, +}; + +static void form_enter(struct sgi_form *) +{ + /* 注册输入法 */ + register_ime(&FORM_CLASS(MODULE_NAME)); + + set_object_text_u(&s_edt_uid.edit, NULL); + set_object_text_u(&s_edt_pwd.edit, NULL); + set_object_focus(&s_edt_uid); + + s_timer = 60; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d秒", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void callback(s32 user) +{ + if (user == ID_INVALID) { + set_object_focus(&s_edt_uid); + } + else if (user == PWD_INVALID) { + set_object_focus(&s_edt_pwd); + } +} + +static void btn_confirm_up(struct sgi_button *) +{ + if (sgi_cmp16(g_passport.mid, s_edt_uid.edit.text) == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"紧急开锁必须由两个管理员开启!", + 0, NULL); + return; + } + sgi_cp16(g_passport.uid, g_passport.mid); + + s32 r = verify_manager_pwd(&g_passport, s_edt_uid.edit.text, + s_edt_pwd.edit.text); + + if (r >= 0) { + sgi_form_show(&FORM_CLASS(fm_unlock)); + } + else if (r == ID_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"用户信息不存在!", + ID_INVALID, callback); + } + else if (r == PWD_INVALID) { + msgbox(&FORM_CLASS(MODULE_NAME), L"密码无效!", + PWD_INVALID, callback); + + if (++s_pwd_retries >= PWD_MAX_RETRIES) { + pwd_alarm(); + } + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, s_widget); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 编号输入框 */ + EDIT_CREATE(s_edt_uid, FORM_CLASS(MODULE_NAME), 346, 86, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + + /* 密码输入框 */ + EDIT_CREATE(s_edt_pwd, FORM_CLASS(MODULE_NAME), 346, 126, 192, 25, 1, + "jht.ttf", 20, text_cl, "cursor.png", IMG_OPTIMIZE | IMG_ALPHA, 12); + s_edt_pwd.edit.pwdchar = 1; + + /* 确认按钮 */ + BUTTON_CREATE(s_btn_confirm, FORM_CLASS(MODULE_NAME), 556, 106, 108, 45, 1, + "btn-confirm-u.png", "btn-confirm-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_confirm.button.up = btn_confirm_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/fm_user_level.cpp b/src/fm_user_level.cpp new file mode 100644 index 0000000..9c2667e --- /dev/null +++ b/src/fm_user_level.cpp @@ -0,0 +1,485 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_user_level + +FORM_MODULE(MODULE_NAME); /* 模块 */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_grid; +static union sgi_object s_btn_save; /* 保存 */ +static union sgi_object s_btn_cancel; /* 取消 */ +static union sgi_object s_btn_prev; /* 上一页 */ +static union sgi_object s_btn_next; /* 下一页 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; +static s32 s_page = 0; +static u32 s_data_size = 0; +static s32 s_record_count = 0; +static struct person_data *s_grid_data = NULL; + +static void grid_load_data(struct sgi_grid *object) +{ + s32 i,j; + s32 space_row_start = 0; + s32 index; + struct person_data *p; + s32 offset; + s32 read_count; + struct tm *tmlocal; + + /* 页数检查 */ + offset = s_page * object->row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + p = s_grid_data + offset; + read_count = s_record_count - offset; + for (i = 0; i < object->row; ) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + object->cells[index].valid = 1; + + switch (j) { + case 0: /* column 0 */ + sgi_sprintf16(object->cells[index].string, + L"%d", s_page * object->row + i + 1); + break; + + case 1: /* column 1 */ + sgi_ncp16(object->cells[index].string, p->uid, + COUNTOF(p->uid)); + break; + + case 2: /* column 2 */ + sgi_ncp16(object->cells[index].string, p->name, + COUNTOF(p->name)); + break; + + case 3: /* column 3 */ + if (p->level == LV_USER) { + object->cells[index].val = 1; + } + else { + object->cells[index].val = 0; + } + break; + + case 4: /* column 4 */ + if (p->level == LV_MANAGER) { + object->cells[index].val = 1; + } + else { + object->cells[index].val = 0; + } + break; + + case 5: /* column 5 */ + if (p->level == LV_ADMIN) { + object->cells[index].val = 1; + } + else { + object->cells[index].val = 0; + } + break; + + case 6: /* column 6 */ + if (p->level == LV_SUPER) { + object->cells[index].val = 1; + } + else { + object->cells[index].val = 0; + } + break; + + default: + break; + + } + } + + i++; + if (--read_count <= 0) { + break; + } + p++; + } + + printf("space row start: %d\n", i); + + /* 剩余行清零 */ + for (; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + object->cells[index].val = 0; + memset(object->cells[index].string, 0, + sizeof(object->cells[index].string)); + } + } +} + +static void grid_init(struct sgi_grid *object) +{ + s32 i,j; + s32 index; + s32 y0; + const s32 row_offset = 67; + const s32 row_h = 26; + + /* */ + object->col = 7; + object->row = 10; + + /* */ + object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + + if (!object->cells) { + return; + } + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * row_h + row_offset; + for (j = 0; j < object->col; ++j) { + index = i * object->col + j; + + switch (j) { + case 0: /* column 0 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 27; + object->cells[index].y = y0; + object->cells[index].w = 44; + object->cells[index].h = row_h; + break; + + case 1: /* column 1 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 71; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 2: /* column 2 */ + object->cells[index].type = GRID_STRING; + object->cells[index].x = object->x + 161; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 3: /* column 3 */ + object->cells[index].type = GRID_RADIO; + object->cells[index].x = object->x + 251; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 4: /* column 4 */ + object->cells[index].type = GRID_RADIO; + object->cells[index].x = object->x + 340; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 5: /* column 5 */ + object->cells[index].type = GRID_RADIO; + object->cells[index].x = object->x + 430; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + case 6: /* column 6 */ + object->cells[index].type = GRID_RADIO; + object->cells[index].x = object->x + 519; + object->cells[index].y = y0; + object->cells[index].w = 89; + object->cells[index].h = row_h; + break; + + default: + break; + } + } + } +} + +static void grid_deinit(struct sgi_grid *object) +{ + free(object->cells); + object->cells = NULL; +} + +static void form_enter(struct sgi_form *) +{ + /* */ + s_page = 0; + s_data_size = 0; + + /* 初始表格 */ + grid_init(&s_grid.grid); + + /* 加载表格数据 */ + s_grid_data = (struct person_data *)open_w(DBD(person), &s_data_size); + s_record_count = s_data_size / sizeof(struct person_data); + grid_load_data(&s_grid.grid); + + printf("load data: %d\n", s_record_count); + + /* 倒计时长 */ + s_timer = 240; +} + +static void form_exit(struct sgi_form *object) +{ + grid_deinit(&s_grid.grid); + + printf("close data: %d\n", s_data_size); + + /* 关闭数据 */ + if (s_grid_data) { + close_w(s_grid_data, s_data_size); + } + + /* 重新加载用户数据 */ + load_person_data(); +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = localtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ +// static u32 next; +// wchar_t buf[64]; +// +// if (SDL_GetTicks() > next) { +// s_timer--; +// if (s_timer <= 0) { +// //s_btn_main.button.up(&s_btn_main.button); +// } +// swprintf(buf, sizeof(buf), L"倒计时:%02d秒", s_timer); +// set_object_text_w(label, buf); +// label->redraw = 1; +// +// next = SDL_GetTicks() + 1000; +// } + + return 0; +} + +static void btn_back_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_log_main)); +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + sgi_form_frame_default(form); + + return 0; +} + +static void save_change(void) +{ + s32 i; + s32 index; + struct person_data *p; + s32 offset; + s32 read_count; + + /* 页数检查 */ + offset = s_page * s_grid.grid.row; + if (!s_grid_data || offset > s_record_count) { + return; + } + + p = s_grid_data + offset; + read_count = s_record_count - offset; + for (i = 0; i < s_grid.grid.row; ++i) { + index = i * s_grid.grid.col; + if (s_grid.grid.cells[index + 3].val) { + p->level = 0; + } + else if (s_grid.grid.cells[index + 4].val) { + p->level = 1; + } + else if (s_grid.grid.cells[index + 5].val) { + p->level = 2; + } + else if (s_grid.grid.cells[index + 6].val) { + p->level = 3; + } + + if (--read_count <= 0) { + break; + } + p++; + } + + if (data_flush(s_grid_data, s_data_size) == 0) { + msgbox(&FORM_CLASS(MODULE_NAME), L"数据保存成功!", 0, NULL); + } +} + +static void btn_save_up(struct sgi_button *) +{ + if (s_grid.grid.changed) { + save_change(); + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + s_grid.grid.changed = 0; + } +} + +static void btn_cancel_up(struct sgi_button *) +{ + if (s_grid.grid.changed) { + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + s_grid.grid.changed = 0; + } +} + +static void callback(s32 user) +{ + +} + +static void btn_prev_up(struct sgi_button *) +{ + if (s_grid.grid.changed) { + msgbox(&FORM_CLASS(MODULE_NAME), L"数据已经改变,请先保存或取消更改!", + 0, NULL); + return; + } + + if (s_page > 0) { + s_page--; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +static void btn_next_up(struct sgi_button *) +{ + if (s_grid.grid.changed) { + msgbox(&FORM_CLASS(MODULE_NAME), L"数据已经改变,请先保存或取消更改!", + 0, NULL); + return; + } + + if (((s_page + 1) * s_grid.grid.row) < s_record_count) { + s_page++; + grid_load_data(&s_grid.grid); + s_grid.grid.redraw = 1; + } +} + +FORM_CREATE_FN(MODULE_NAME) +{ + SDL_Color color = {255,255,255,0}; + SDL_Color text_cl = {0, 0, 0, 0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "bg-2.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 4, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, FORM_CLASS(MODULE_NAME), 634, 36, 150, 25, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* */ + GRID_CREATE(s_grid, FORM_CLASS(MODULE_NAME), 82, 44, 636, 333, 1, + "jht.ttf", 20, color, "grid-level.png", "grid-sel.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* */ + BUTTON_CREATE(s_btn_save, FORM_CLASS(MODULE_NAME), 153, 388, 85, 35, 1, + "btn-save-s-u.png", "btn-save-s-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_save.button.up = btn_save_up; + + /* */ + BUTTON_CREATE(s_btn_cancel, FORM_CLASS(MODULE_NAME), 251, 388, 85, 35, 1, + "btn-cancel-s-u.png", "btn-cancel-s-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_cancel.button.up = btn_cancel_up; + + /* */ + BUTTON_CREATE(s_btn_prev, FORM_CLASS(MODULE_NAME), 482, 388, 73, 29, 1, + "btn-prev-u.png", "btn-prev-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_prev.button.up = btn_prev_up; + + /* */ + BUTTON_CREATE(s_btn_next, FORM_CLASS(MODULE_NAME), 572, 388, 73, 29, 1, + "btn-next-u.png", "btn-next-d.png", NULL, NULL, + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_next.button.up = btn_next_up; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, FORM_CLASS(MODULE_NAME), 32, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-back.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_back.button.up = btn_back_up; + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, FORM_CLASS(MODULE_NAME), 684, 374, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-t.png", "btn-home.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + FORM_CLASS(MODULE_NAME).enter = form_enter; + FORM_CLASS(MODULE_NAME).exit = form_exit; + FORM_CLASS(MODULE_NAME).frame = form_frame; + + return 0; +} +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/src/global_def.h b/src/global_def.h new file mode 100644 index 0000000..40644dd --- /dev/null +++ b/src/global_def.h @@ -0,0 +1,740 @@ +#ifndef GLOBAL_DEF_H +#define GLOBAL_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "SDL.h" +#include "SDL_image.h" +#include "SDL_ttf.h" +#include "SDL_mixer.h" +#include "sgi_types.h" +#include "lock.h" + +/* common define */ +#define MAX_PATH 260 +#define IMG_OPTIMIZE (1 << 0) +#define IMG_ALPHA (1 << 1) +#define X_RES 800 +#define Y_RES 480 + +#define DT_LEFT 0 +#define DT_CENTER 1 +#define DT_RIGHT 2 + +/* timeout define */ +#define TIMEOUT_IDENT 60 + +/* fingerprint module define */ +#define FPR_SIGNAL SIGRTMIN + 1 + +#define FPR_IDENTIFY 1 +#define FPR_ENROLL_1 2 +#define FPR_ENROLL_2 3 +#define FPR_ENROLL_3 4 +#define FPR_QUIT 15 + +/* object type define */ +#define SGI_WINDOW 1 +#define SGI_PICTURE 2 +#define SGI_LABEL 3 +#define SGI_EDIT 4 +#define SGI_BUTTON 5 +#define SGI_IME 6 +#define SGI_GRID 7 +#define SGI_FORM 8 +#define SGI_PHOTO 9 +#define SGI_MSGBOX 10 +#define SGI_RADIO 11 +#define SGI_CHECK 12 +#define SGI_UPDOWN 13 +#define SGI_BOX 14 +#define SGI_INDICATOR 15 + +/* grid col type */ +#define GRID_STRING 0 +#define GRID_BUTTON 1 +#define GRID_RADIO 2 + +/* photo type define */ +#define PHO_SAMPLE 1 +#define PHO_REAL 2 +#define PHOTO_SAMPLE_PATH "/sdcard/data/photo" +#define PHOTO_REAL_PATH "/sdcard/log/photo" + +/* text style define */ +#define DEL_CHAR 0x0008 +#define SPACE 2 +#define EDIT_SPACE 0 +#define RADIO_SPACE 0 +#define CHECK_SPACE 0 + +#define MSK_DIGIT (1 << 0) +#define MSK_ALPHA (1 << 2) +#define MSK_CHN (1 << 3) + +/* ime & box define */ +#define KEY_NUMS 38 +#define SELECTOR_NUMS 10 +#define BOX_NUMS 42 +#define CELL_EMPTY(n) (((n) & 0x3) == 0) +#define CELL_VALID(n) (((n) & 0x3) == 1) +#define CELL_BORROW(n) (((n) & 0x3) == 3) +#define BOX_TYPE_GUN 0 +#define BOX_TYPE_BULLET 1 + +/* data define */ +#define VALID_PASSPORT (1u << 31) + +#define USR_FPR_MASK (~(3 << 0)) +#define USR_FPR_VALID (1 << 0) +#define USR_FPR_INVALID (2 << 0) +#define USR_CARD_MASK (~(3 << 2)) +#define USR_CARD_VALID (1 << 2) +#define USR_CARD_INVALID (2 << 2) +#define USR_PWD_MASK (~(3 << 4)) +#define USR_PWD_VALID (1 << 4) +#define USR_PWD_INVALID (2 << 4) + +#define MGR_FPR_MASK (~(3 << 8)) +#define MGR_FPR_VALID (1 << 8) +#define MGR_FPR_INVALID (2 << 8) +#define MGR_CARD_MASK (~(3 << 10)) +#define MGR_CARD_VALID (1 << 10) +#define MGR_CARD_INVALID (2 << 10) +#define MGR_PWD_MASK (~(3 << 12)) +#define MGR_PWD_VALID (1 << 12) +#define MGR_PWD_INVALID (2 << 12) + +#define MIN_PWD_LEN 6 + +#define LV_USER 0 +#define LV_MANAGER 1 +#define LV_ADMIN 2 +#define LV_SUPER 3 +#define LV_SPEC 4 + +#define SR_FPR 1 +#define SR_CARD 2 + +#define MSG_TIP 1 + +#define REG_NONE 0 +#define REG_NEW 1 +#define REG_MODIFY 2 +#define REG_UPDATE 3 + +#define SUCCESS 0 +#define ID_INVALID -1 +#define PWD_INVALID -2 +#define PWD_NOT_MATCH -3 +#define PWD_SHORTEST -4 +#define FPR_FAIL -5 +#define ID_EXIST -6 +#define CODE_INVALID -7 +#define APPEND_FAIL -8 +#define REGISTER_FAIL -9 +#define ENROLL_FAIL -10 +#define DEL_FAIL -11 + +/* download define */ +#define UDISK_DRV "/proc/scsi/usb-storage" +#define UDISK_DEV "/udisk" + +/* monitor define */ +#define LOCK_SCAN_CYCLE 100 +#define REMIT_TIME 30000 +#define POWER_REMIT_TIME 7200000 +#define BORROW_REMIT_TIME (24 * 3600 * 1000) +#define AUTHORIZE_TIME 600000 +#define FORCE_OPEN_DOOR 1 +#define FORCE_UNLOCK 2 +#define POWER_LOST 3 +#define BORROW_TIMEOUT 4 +#define PWD_ERROR 5 + +#define PWD_MAX_RETRIES 3 + +#define LOCK_MON_COUNT 1 +#define DOOR_MON_COUNT 2 +#define POWER_MON_COUNT 2 + +#define ALARM_DOOR_EN (1 << 0) +#define ALARM_DOOR_EX_EN (1 << 1) +#define ALARM_LOCK_EN (1 << 2) +#define ALARM_POWER_EN (1 << 3) +#define ALARM_BORROW_EN (1 << 4) +#define ALARM_PWD_EN (1 << 5) + +#define POWER_AC 0 +#define POWER_BATTERY 1 + +/* main control board */ +#define MFCARD_MAGIC 'E' +#define MFCARD_IOCTL_ALARM _IOW(MFCARD_MAGIC, 1, int) +#define MFCARD_IOCTL_PW_CTRL _IOW(MFCARD_MAGIC, 2, int) +#define MFCARD_IOCTL_DOOR_CTRL _IOW(MFCARD_MAGIC, 3, int) +#define MFCARD_IOCTL_CARD_START _IOW(MFCARD_MAGIC, 4, int) +#define MFCARD_IOCTL_CARD_STATE _IOR(MFCARD_MAGIC, 5, int) +#define MFCARD_IOCTL_CARD_READ _IOR(MFCARD_MAGIC, 6, int) +#define MFCARD_IOCTL_FPR_STATE _IOR(MFCARD_MAGIC, 7, int) +#define MFCARD_IOCTL_DOOR_FB _IOR(MFCARD_MAGIC, 8, int) +#define MFCARD_IOCTL_PW_JC _IOR(MFCARD_MAGIC, 9, int) +#define MFCARD_IOCTL_QWZ1 _IOR(MFCARD_MAGIC, 10, int) +#define MFCARD_IOCTL_QWZ2 _IOR(MFCARD_MAGIC, 11, int) + +#define DOOR_CLOSE 0 +#define DOOR_OPEN 1 + +#define ALARM_ON 1 +#define ALARM_OFF 0 + +/* message define */ +#define SGI_MOUSEDOWN 0x1001 +#define SGI_MOUSEUP 0x1002 +#define SGI_CHAR 0x1003 + +/* net define */ +#define SERVER_IP "192.168.1.8" +#define SERVER_PORT 6000 +#define NET_MAGIC 0x5AA56699 + +#define POOL_INIT_NUMS 100 +#define POOL_REALLOC_NUMS 20 +#define POOL_MAX_NUMS 2000 + +#define CMD_NONE 0 +#define CMD_HEARTBEAT 1 +#define CMD_TIME_ADJUST 2 +#define CMD_DATA_ALARM 3 +#define CMD_DATA_BORROW 4 +#define CMD_DATA_RETURN 5 +#define CMD_DATA_SYSTEM 6 +#define CMD_DATA_MANAGER 7 +#define CMD_DATA_REPORT_BORROW 8 +#define CMD_DATA_REPORT_RETURN 9 + +#define BOX_CODE_LEN (16 * sizeof(u16)) + +#define NET_MONITOR_CYCLE 1000 +#define NET_DOWN_CYCLE 10000 +#define NET_LINK_CYCLE 5000 +#define TIME_ADJUST_CYCLE 3600000 + +enum sgi_log_type { + LOG_MANAGER = 0, + LOG_BORROW, + LOG_RETURN, + LOG_ALARM, + LOG_SYSTEM, + LOG_MAX, +}; + +enum sgi_ime_type { + IME_CHAR = 0, + IME_SYMBOL, + IME_PINYIN, +}; + +struct sgi_msg { + u16 type; + s16 wparam; + s32 lparam; +}; + +struct sgi_font { + char *name; + u32 size; + TTF_Font *font; +}; + +struct sgi_image { + char *name; + u32 flags; + SDL_Surface *image; +}; + +struct sgi_widget { + s16 x; + s16 y; + s16 w; + s16 h; + struct sgi_image image; +}; + +struct sgi_key { + u16 state; + s16 index; + s16 x; + s16 y; + s16 w; + s16 h; +}; + +struct sgi_cell { + u16 state; + s16 tag; + s16 x; + s16 y; + s16 w; + s16 h; +}; + +struct sgi_ime_caption { + u16 text[KEY_NUMS][4]; +}; + +struct sgi_ime_word { + u16 word[KEY_NUMS]; +}; + +struct sgi_ime_chinese { + u16 syllables[8]; + u16 page; + u16 count; + wchar_t *chinese; +}; + +struct sgi_window { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + s32 reallocated; + + struct sgi_image image; + struct sgi_widget *widget; + + int (*init)(struct sgi_window *); + void (*deinit)(struct sgi_window *); + int (*frame)(struct sgi_window *); + void (*render)(struct sgi_window *, SDL_Surface *); +}; + +struct sgi_picture { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + + u32 state; + struct sgi_image image; + + s32 (*init)(struct sgi_picture *); + void (*deinit)(struct sgi_picture *); + s32 (*frame)(struct sgi_picture *); + void (*render)(struct sgi_picture *, SDL_Surface *); +}; + +struct sgi_photo { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + struct sgi_form *parent; + u32 redraw; + SDL_Surface *surface; + + s32 (*init)(struct sgi_photo *); + void (*deinit)(struct sgi_photo *); + s32 (*frame)(struct sgi_photo *); + void (*render)(struct sgi_photo *, SDL_Surface *); +}; + +struct sgi_indicator { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + u32 redraw; + + s32 state; + struct sgi_image image[2]; + + s32 (*init)(struct sgi_indicator *); + void (*deinit)(struct sgi_indicator *); + s32 (*frame)(struct sgi_indicator *); + void (*render)(struct sgi_indicator *, SDL_Surface *); +}; + +struct sgi_label { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + + s32 align; + SDL_Color fcolor; + u32 bcolor; + s32 tag; + + u16 caption[64]; + struct sgi_font font; + + s32 (*init)(struct sgi_label *); + void (*deinit)(struct sgi_label *); + s32 (*frame)(struct sgi_label *); + void (*render)(struct sgi_label *, SDL_Surface *); +}; + +struct sgi_edit { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + u32 handle; + + s32 align; + SDL_Color fcolor; + u32 bcolor; + + u16 text[64]; + struct sgi_font font; + struct sgi_image image; + + u8 readonly; + u8 word_max; + u8 focus; + u8 cursor; + u32 cursor_timer; + u16 pwdchar; + u16 mask; + + s32 (*init)(struct sgi_edit *); + void (*deinit)(struct sgi_edit *); + s32 (*frame)(struct sgi_edit *); + void (*render)(struct sgi_edit *, SDL_Surface *); +}; + +struct sgi_button { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + + u32 hide; + u32 state; + struct sgi_image back[3]; + struct sgi_image front; + + s32 (*init)(struct sgi_button *); + void (*deinit)(struct sgi_button *); + s32 (*frame)(struct sgi_button *); + void (*render)(struct sgi_button *, SDL_Surface *); + + void (*down)(struct sgi_button *); + void (*up)(struct sgi_button *); + void (*click)(struct sgi_button *); +}; + +struct sgi_ime { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u16 hide; + u16 state; + u16 mode; + u16 ch; + struct sgi_font font; + struct sgi_image back[2]; + struct sgi_key *key; + const struct sgi_ime_word *word; + const struct sgi_ime_caption *caption; + + struct sgi_key *selector; + struct sgi_ime_chinese chinese; + + u32 redraw; + + s32 (*init)(struct sgi_ime *); + void (*deinit)(struct sgi_ime *); + s32 (*frame)(struct sgi_ime *); + void (*render)(struct sgi_ime *, SDL_Surface *); + + void (*down)(struct sgi_ime *); + void (*up)(struct sgi_ime *); +}; + +struct sgi_box { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u16 hide; + u16 state; + struct sgi_font font; + struct sgi_image back[4]; + struct sgi_cell cell[BOX_NUMS]; + const u8 *cell_addr; + + u32 redraw; + + s32 (*init)(struct sgi_box *); + void (*deinit)(struct sgi_box *); + s32 (*frame)(struct sgi_box *); + void (*render)(struct sgi_box *, SDL_Surface *); + + void (*down)(struct sgi_box *); + void (*up)(struct sgi_box *); +}; + +struct sgi_msgbox { + u16 type; + s16 z; + s16 x; + s16 y; + s16 w; + s16 h; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + struct sgi_font font; + struct sgi_image image[4]; + struct sgi_key button; + + u16 text[128]; + s32 style; + + s32 (*init)(struct sgi_msgbox *); + void (*deinit)(struct sgi_msgbox *); + s32 (*frame)(struct sgi_msgbox *); + void (*render)(struct sgi_msgbox *, SDL_Surface *); + + u32 user; + void (*callback)(s32); +}; + +struct sgi_radio { + u16 type; + s16 x,y,w,h,z; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + u32 handle; + u16 state; + s16 value; + struct sgi_image image[2]; + + s32 (*init)(struct sgi_radio *); + void (*deinit)(struct sgi_radio *); + s32 (*frame)(struct sgi_radio *); + void (*render)(struct sgi_radio *, SDL_Surface *); + + void (*up)(struct sgi_radio *); +}; + +struct sgi_check { + u16 type; + s16 x,y,w,h,z; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + u32 handle; + u16 state; + s16 value; + struct sgi_image image[2]; + + s32 (*init)(struct sgi_check *); + void (*deinit)(struct sgi_check *); + s32 (*frame)(struct sgi_check *); + void (*render)(struct sgi_check *, SDL_Surface *); + + void (*up)(struct sgi_check *); +}; + +struct sgi_updown { + u16 type; + s16 x,y,w,h,z,tw; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + u32 handle; + u16 state[2]; + s32 value; + + SDL_Color fcolor; + struct sgi_font font; + struct sgi_image image[2]; + + s32 (*init)(struct sgi_updown *); + void (*deinit)(struct sgi_updown *); + s32 (*frame)(struct sgi_updown *); + void (*render)(struct sgi_updown *, SDL_Surface *); +}; + +struct grid_cell { + u16 type; + s16 x; + s16 y; + s16 w; + s16 h; + u16 state; + s16 valid; + s16 val; + u16 string[32]; +}; + +struct sgi_grid { + u16 type; + s16 x,y,w,h,z; + + s16 row; + s16 col; + s16 select_index; + s16 readonly; + s32 changed; + struct grid_cell *cells; + + s32 initialized; + struct sgi_form *parent; + + u32 redraw; + u32 handle; + SDL_Color fcolor; + struct sgi_font font; + struct sgi_image back; + struct sgi_image action; + + s32 (*init)(struct sgi_grid *); + void (*deinit)(struct sgi_grid *); + s32 (*frame)(struct sgi_grid *); + void (*render)(struct sgi_grid *, SDL_Surface *); + + void (*down)(struct sgi_grid *, s32 row); + void (*up)(struct sgi_grid *, s32 row); +}; + +union sgi_object { + u16 type; + struct sgi_window window; + struct sgi_picture picture; + struct sgi_label label; + struct sgi_edit edit; + struct sgi_button button; + struct sgi_ime ime; + struct sgi_grid grid; + struct sgi_photo photo; + struct sgi_msgbox msgbox; + struct sgi_radio radio; + struct sgi_check check; + struct sgi_updown updown; + struct sgi_box box; + struct sgi_indicator indicator; +}; + +struct sgi_form { + char *name; + std::vector form; + std::list msg; + struct sgi_window *wnd; + struct sgi_ime *ime; + struct sgi_msgbox *msgbox; + + s32 initialized; + u16 redraw; + u16 dirty; + s16 x1,y1,x2,y2; + u32 focus_handle; + + s32 (*init)(struct sgi_form *); + void (*deinit)(struct sgi_form *); + s32 (*frame)(struct sgi_form *); + void (*render)(struct sgi_form *, SDL_Surface *); + + void (*enter)(struct sgi_form *); + void (*exit)(struct sgi_form *); + + void (*add)(union sgi_object *); + void (*del)(union sgi_object *); + void (*sort)(s32 order); +}; + +struct sgi_form_list { + struct sgi_form *form; + s32 (*create)(void); + void (*destroy)(void); + s32 created; +}; + +struct udisk_info { + char vendor[32]; + char product[32]; + char sn[32]; + u32 total; + u32 avail; +}; + +#endif diff --git a/src/global_func.h b/src/global_func.h new file mode 100644 index 0000000..725ac3c --- /dev/null +++ b/src/global_func.h @@ -0,0 +1,447 @@ +#ifndef GLOBAL_FUNC_H +#define GLOBAL_FUNC_H + +#include "global_def.h" +#include "global_macro.h" +#include "sgi_string.h" +#include "sgi_data.h" +#include "sgi_log.h" + +extern const char *get_resource_path(void); + +/* global variable declare */ +extern struct passport_data g_passport; +extern struct alarm_data g_alarm_data; +extern pthread_t g_fpr_thread; +extern struct sgi_ime g_sgi_ime; +extern struct sgi_msgbox g_sgi_msgbox; +extern const u8 g_box_addr[BOX_NUMS]; +extern s32 g_data_update_state; + +/* form declare */ +FORM_DECLARE(fm_main) +FORM_DECLARE(fm_menu) + +FORM_DECLARE(fm_borrow_fpr_user) +FORM_DECLARE(fm_borrow_card_user) +FORM_DECLARE(fm_borrow_pwd_user) +FORM_DECLARE(fm_borrow_fpr_manager) +FORM_DECLARE(fm_borrow_card_manager) +FORM_DECLARE(fm_borrow_pwd_manager) +FORM_DECLARE(fm_borrow_photo_user) +FORM_DECLARE(fm_borrow_unlock) + +FORM_DECLARE(fm_return_fpr_user) +FORM_DECLARE(fm_return_fpr_manager) +FORM_DECLARE(fm_return_card_user) +FORM_DECLARE(fm_return_card_manager) +FORM_DECLARE(fm_return_pwd_user) +FORM_DECLARE(fm_return_pwd_manager) +FORM_DECLARE(fm_return_photo_user) +FORM_DECLARE(fm_return_unlock) +FORM_DECLARE(fm_chpwd) + +FORM_DECLARE(fm_level) +FORM_DECLARE(fm_box_manage) +FORM_DECLARE(fm_log_main) +FORM_DECLARE(fm_system) +FORM_DECLARE(fm_info_choice) +FORM_DECLARE(fm_info_register) +FORM_DECLARE(fm_reg_person) +FORM_DECLARE(fm_reg_photo) +FORM_DECLARE(fm_reg_pwd) +FORM_DECLARE(fm_reg_fpr1_1) +FORM_DECLARE(fm_reg_fpr1_2) +FORM_DECLARE(fm_reg_fpr1_3) +FORM_DECLARE(fm_reg_gun) +FORM_DECLARE(fm_reg_bullet) +FORM_DECLARE(fm_reg_unit) +FORM_DECLARE(fm_reg_box) +FORM_DECLARE(fm_info_stat) +FORM_DECLARE(fm_stat_unit) +FORM_DECLARE(fm_stat_box) +FORM_DECLARE(fm_stat_person) +FORM_DECLARE(fm_stat_bullet) +FORM_DECLARE(fm_stat_gun) +FORM_DECLARE(fm_timing) +FORM_DECLARE(fm_unlock) +FORM_DECLARE(fm_alarm) +FORM_DECLARE(fm_log_manager) +FORM_DECLARE(fm_log_alarm) +FORM_DECLARE(fm_log_borrow) +FORM_DECLARE(fm_log_return) +FORM_DECLARE(fm_log_system) +FORM_DECLARE(fm_user_level) +FORM_DECLARE(fm_menu_pwd) +FORM_DECLARE(fm_alarm_pwd) +FORM_DECLARE(fm_unlock_pwd) +FORM_DECLARE(fm_mon_setting) +FORM_DECLARE(fm_download) +FORM_DECLARE(fm_safecheck) + +#define FORM_LIST_FILL_ALL \ + FORM_LIST_ITEM(fm_main), \ + FORM_LIST_ITEM(fm_menu), \ + \ + FORM_LIST_ITEM(fm_borrow_fpr_user), \ + FORM_LIST_ITEM(fm_borrow_card_user), \ + FORM_LIST_ITEM(fm_borrow_pwd_user), \ + FORM_LIST_ITEM(fm_borrow_fpr_manager), \ + FORM_LIST_ITEM(fm_borrow_card_manager), \ + FORM_LIST_ITEM(fm_borrow_pwd_manager), \ + FORM_LIST_ITEM(fm_borrow_photo_user), \ + FORM_LIST_ITEM(fm_borrow_unlock), \ + \ + FORM_LIST_ITEM(fm_return_fpr_manager), \ + FORM_LIST_ITEM(fm_return_fpr_user), \ + FORM_LIST_ITEM(fm_return_card_user), \ + FORM_LIST_ITEM(fm_return_card_manager), \ + FORM_LIST_ITEM(fm_return_pwd_user), \ + FORM_LIST_ITEM(fm_return_pwd_manager), \ + FORM_LIST_ITEM(fm_return_photo_user), \ + FORM_LIST_ITEM(fm_return_unlock), \ + \ + FORM_LIST_ITEM(fm_chpwd), \ + \ + FORM_LIST_ITEM(fm_level), \ + FORM_LIST_ITEM(fm_box_manage), \ + FORM_LIST_ITEM(fm_log_main), \ + FORM_LIST_ITEM(fm_system), \ + FORM_LIST_ITEM(fm_info_choice), \ + FORM_LIST_ITEM(fm_info_register), \ + FORM_LIST_ITEM(fm_reg_person), \ + FORM_LIST_ITEM(fm_reg_photo), \ + FORM_LIST_ITEM(fm_reg_pwd), \ + FORM_LIST_ITEM(fm_reg_fpr1_1), \ + FORM_LIST_ITEM(fm_reg_fpr1_2), \ + FORM_LIST_ITEM(fm_reg_fpr1_3), \ + FORM_LIST_ITEM(fm_reg_gun), \ + FORM_LIST_ITEM(fm_reg_bullet), \ + FORM_LIST_ITEM(fm_reg_unit), \ + FORM_LIST_ITEM(fm_reg_box), \ + FORM_LIST_ITEM(fm_info_stat), \ + FORM_LIST_ITEM(fm_stat_unit), \ + FORM_LIST_ITEM(fm_stat_box), \ + FORM_LIST_ITEM(fm_stat_person), \ + FORM_LIST_ITEM(fm_stat_bullet), \ + FORM_LIST_ITEM(fm_stat_gun), \ + FORM_LIST_ITEM(fm_timing), \ + FORM_LIST_ITEM(fm_unlock), \ + FORM_LIST_ITEM(fm_alarm), \ + FORM_LIST_ITEM(fm_log_manager), \ + FORM_LIST_ITEM(fm_log_alarm), \ + FORM_LIST_ITEM(fm_log_borrow), \ + FORM_LIST_ITEM(fm_log_return), \ + FORM_LIST_ITEM(fm_log_system), \ + FORM_LIST_ITEM(fm_user_level), \ + FORM_LIST_ITEM(fm_menu_pwd), \ + FORM_LIST_ITEM(fm_alarm_pwd), \ + FORM_LIST_ITEM(fm_unlock_pwd), \ + FORM_LIST_ITEM(fm_mon_setting), \ + FORM_LIST_ITEM(fm_download), \ + FORM_LIST_ITEM(fm_safecheck), + +/* uart.cpp */ +extern int open_comm(void); +extern void close_comm(void); +extern int transfer(u8 *tx, u32 tx_len, u8 *rx, u32 rx_len, u32 timeout); +extern int uart_receive(u8 *rx, u32 rx_len, u32 timeout); +extern SDL_Surface *clone_surface(SDL_Surface *image); +extern void release_clone_surface(SDL_Surface *image); + +/* sgi_base.cpp */ +extern u32 request_handle(void); +extern void strncpy_u2a(char *dst, u16 *src, s32 size); +extern void strncpy_u(u16 *dst, u16 *src, s32 size); +extern int strlen_u(u16 *src); +extern void strncpy_w(u16 *dst, wchar_t *src, s32 size); +extern s32 strncmp_u(u16 *src1, u16 *src2, s32 size); +extern void set_object_default_func(struct sgi_form *form); +extern void set_object_default_func(union sgi_object *object); +extern void invalidate_rect(struct sgi_form *form, s16 x1, s16 y1, s16 x2, s16 y2); +extern void set_object_pos(union sgi_object *object, s16 x, s16 y, s16 w, s16 h, s16 z); +extern void set_object_parent(union sgi_object *object, struct sgi_form *form); +extern void set_object_image(union sgi_object *object, char *image1, char *image2, + char *image3, char *image4, u32 flags); +extern void set_object_font(union sgi_object *object, char *name, u32 size, + SDL_Color color); +extern void form_memset(struct sgi_form *form); +extern void sgi_edit_insert_text(struct sgi_edit *object, u16 text); +extern void set_object_text_u(struct sgi_label *object, u16 *text); +extern void set_object_text_u(struct sgi_edit *object, u16 *text); +extern void set_object_text_w(struct sgi_label *object, wchar_t *text); +extern void set_object_text_w(struct sgi_edit *object, wchar_t *text); +extern void get_object_text_u(struct sgi_label *object, u16 *text); +extern void get_object_text_u(struct sgi_edit *object, u16 *text); +extern void set_object_focus(union sgi_object *object); +extern void register_window(struct sgi_form *form, struct sgi_window *wnd); +extern void register_ime(struct sgi_form *form); +extern void msgbox(struct sgi_form *form, w32 *text, s32 user, void (*callback)(s32)); +extern SDL_Surface *load_photo(struct passport_data *pass, s32 type); +extern void unload_photo(struct sgi_photo *photo); + +/* sgi_base_picture.cpp */ +extern s32 sgi_picture_init_default(struct sgi_picture *object); +extern void sgi_picture_deinit_default(struct sgi_picture *object); +extern s32 sgi_picture_frame_default(struct sgi_picture *object); +extern void sgi_picture_render_default(struct sgi_picture *object, + SDL_Surface *screen); +extern void sgi_photo_render_default(struct sgi_photo *object, + SDL_Surface *screen); + +/* sgi_base_indicator.cpp */ +extern s32 sgi_indicator_init_default(struct sgi_indicator *object); +extern void sgi_indicator_deinit_default(struct sgi_indicator *object); +extern s32 sgi_indicator_frame_default(struct sgi_indicator *object); +extern void sgi_indicator_render_default(struct sgi_indicator *object, + SDL_Surface *screen); + +/* sgi_base_label.cpp */ +extern s32 sgi_label_init_default(struct sgi_label *object); +extern void sgi_label_deinit_default(struct sgi_label *object); +extern s32 sgi_label_frame_default(struct sgi_label *object); +extern void sgi_label_render_default(struct sgi_label *object, + SDL_Surface *screen); + +/* sgi_base_window.cpp */ +extern s32 sgi_window_init_default(struct sgi_window *object); +extern void sgi_window_deinit_default(struct sgi_window *object); +extern s32 sgi_window_frame_default(struct sgi_window *object); +extern void sgi_window_render_default(struct sgi_window *object, + SDL_Surface *screen); + +/* sgi_base_edit.cpp */ +extern s32 sgi_edit_init_default(struct sgi_edit *object); +extern void sgi_edit_deinit_default(struct sgi_edit *object); +extern s32 sgi_edit_frame_default(struct sgi_edit *object); +extern void sgi_edit_render_default(struct sgi_edit *object, + SDL_Surface *screen); + +/* sgi_base_button.cpp */ +extern s32 sgi_button_init_default(struct sgi_button *object); +extern void sgi_button_deinit_default(struct sgi_button *object); +extern s32 sgi_button_frame_default(struct sgi_button *object); +extern void sgi_button_render_default(struct sgi_button *object, + SDL_Surface *screen); +extern void sgi_button_down_default(struct sgi_button *object); +extern void sgi_button_up_default(struct sgi_button *object); +extern void sgi_button_click_default(struct sgi_button *object); + +/* sgi_base_ime.cpp */ +extern void sgi_ime_create(void); +extern s32 sgi_ime_init_default(struct sgi_ime *object); +extern void sgi_ime_deinit_default(struct sgi_ime *object); +extern s32 sgi_ime_frame_default(struct sgi_ime *object); +extern void sgi_ime_render_default(struct sgi_ime *object, SDL_Surface *screen); +extern wchar_t *decode_syllables(const u16 *syllables); + +/* sgi_base_box.cpp */ +extern s32 sgi_box_init_default(struct sgi_box *object); +extern void sgi_box_deinit_default(struct sgi_box *object); +extern s32 sgi_box_frame_default(struct sgi_box *object); +extern void sgi_box_render_default(struct sgi_box *object, SDL_Surface *screen); +extern void sgi_box_down_default(struct sgi_box *object); +extern void sgi_box_up_default(struct sgi_box *object); + +/* sgi_base_grid.cpp */ +extern s32 sgi_grid_init_default(struct sgi_grid *object); +extern void sgi_grid_deinit_default(struct sgi_grid *object); +extern s32 sgi_grid_frame_default(struct sgi_grid *object); +extern void sgi_grid_render_default(struct sgi_grid *object, SDL_Surface *screen); + + +/* sgi_base_form.cpp */ +extern s32 sgi_form_init_default(struct sgi_form *form); +extern void sgi_form_deinit_default(struct sgi_form *form); +extern s32 sgi_form_frame_default(struct sgi_form *form); +extern void sgi_form_render_default(struct sgi_form *form, SDL_Surface *screen); + +/* sgi_base_msgbox.cpp */ +extern void sgi_msgbox_create(void); +extern s32 sgi_msgbox_init_default(struct sgi_msgbox *object); +extern void sgi_msgbox_deinit_default(struct sgi_msgbox *object); +extern s32 sgi_msgbox_frame_default(struct sgi_msgbox *object); +extern void sgi_msgbox_render_default(struct sgi_msgbox *object, SDL_Surface *screen); + +/* sgi_base_radio.cpp */ +extern s32 sgi_radio_init_default(struct sgi_radio *object); +extern void sgi_radio_deinit_default(struct sgi_radio *object); +extern s32 sgi_radio_frame_default(struct sgi_radio *object); +extern void sgi_radio_render_default(struct sgi_radio *object, + SDL_Surface *screen); + +/* sgi_base_check.cpp */ +extern s32 sgi_check_init_default(struct sgi_check *object); +extern void sgi_check_deinit_default(struct sgi_check *object); +extern s32 sgi_check_frame_default(struct sgi_check *object); +extern void sgi_check_render_default(struct sgi_check *object, + SDL_Surface *screen); + +/* sgi_base_updown.cpp */ +extern s32 sgi_updown_init_default(struct sgi_updown *object); +extern void sgi_updown_deinit_default(struct sgi_updown *object); +extern s32 sgi_updown_frame_default(struct sgi_updown *object); +extern void sgi_updown_render_default(struct sgi_updown *object, + SDL_Surface *screen); + +/* sgi_resource.cpp */ +extern int initialize_resource(SDL_Surface *screen); +extern void destroy_resource(void); +extern TTF_Font *request_font(char *id, int font_size); +extern void release_font(void *font); +extern SDL_Surface *request_image(char *id, int flags); +extern void release_image(void *image); +extern Mix_Chunk *request_wav(char *id); +extern void release_wav(void *wav); +extern Mix_Music *request_mp3(char *id); +extern void release_mp3(void *mp3); +extern void play_effect(void); +extern void play_effect_fpr(void); + +/* fingerprint.cpp */ +extern int fpr_init(void); +extern void fpr_deinit(void); +extern int fpr_open(void); +extern int fpr_close(void); +extern int fpr_get_ver(u32 *ver); +extern int fpr_enroll_start(u32 uid); +extern int fpr_enroll_1(void); +extern int fpr_enroll_2(void); +extern int fpr_enroll_3(void); +extern int fpr_find_free_area(void); +extern int fpr_delete_user(u32 uid); +extern int fpr_check_press_finger(u32 *state); +extern int fpr_identify(u32 *match_id); +extern int fpr_capture_finger(u32 timeout); +extern int fpr_capture_cancel(void); + +/* finger_intf.cpp */ +extern s32 fpr_get_cancel_flag(void); +extern void fpr_set_cancel_flag(void); +extern s32 fpr_get_busy_flag(void); +extern u32 fpr_get_result(void); +extern s32 fpr_get_error_flag(void); +extern s32 fpr_module_init(void); +extern void fpr_module_deinit(void); +extern void fpr_module_trigger(s32 ops); + +/* sgi_form_manage.cpp */ +extern s32 app_loop(SDL_Surface *screen); +extern void sgi_form_show(struct sgi_form *form); + +/* sgi_data.cpp */ +extern void *open_w(const char *name, size_t *size); +extern void close_w(void *ptr, size_t size); +extern void *open_r(const char *name, size_t *size); +extern void close_r(void *ptr, size_t size); +extern s32 data_flush(void *ptr, size_t size); +extern s32 data_open(void); +extern s32 search_uid(struct passport_data *pass, s32 type, u32 param); +extern s32 search_mid(struct passport_data *pass, s32 type, u32 param); +extern s32 verify_user_pwd(struct passport_data *pass, u16 *uid, u16 *pwd); +extern s32 verify_manager_pwd(struct passport_data *pass, u16 *uid, u16 *pwd); +extern s32 change_pwd(u16 *uid, u16 *old_pwd, u16 *new_pwd); +extern struct person_data *get_person_reg_data(void); +extern void person_reg_data_clear(void); +extern s32 register_person(struct person_data_mem *person); +extern s32 register_gun(struct gun_data *gun); +extern s32 register_box(struct box_data *box); +extern s32 register_unit(struct unit_data *unit); +extern struct box_info *get_box_info(void); +extern struct unit_data *get_unit_info(void); +extern s32 enroll_borrow(struct passport_data *pass, u32 *cells); +extern s32 enroll_return(struct passport_data *pass, u32 *cells); +extern u16 *get_box_code(void); +extern u32 get_log_no(enum sgi_log_type type); +extern s32 search_borrow_info(struct passport_data *pass); +extern s32 load_person_data(void); +extern u8 *get_return_info(u16 *uid); +extern s32 get_lock_list(void); +extern void set_lock_list(s32 addr); +extern s32 update_person(struct person_data_mem *data); +extern struct gun_data *get_gun_reg_data(void); +extern s32 delete_person(struct person_data_mem *data); +extern s32 update_gun(struct gun_data *gun); +extern s32 delete_gun(struct gun_data *data); +extern s32 copy_file(char *out, char *in); + +/* sgi_log.cpp */ +extern void record_alarm_log(wchar_t *content); +extern void record_alarm_log(u16 *content); +extern void record_manager_log(u16 *name, wchar_t *content); +extern void record_system_log(u16 *name, wchar_t *content); +extern void record_borrow_log(struct passport_data *pass, + struct box_info *info); +extern void record_return_log(struct passport_data *pass, + struct box_info *info); +extern void recorcd_borrow_report(struct passport_data *pass, int type, + int nums); +extern void recorcd_return_report(struct passport_data *pass, int type, + int nums); +extern void mark_to_alarm_file(u32 id); +extern void mark_to_system_file(u32 id); +extern void mark_to_manager_file(u32 id); +extern void mark_to_report_file(u32 id, s32 type); +extern void mark_to_borrow_file(u32 id, s32 type); + +/* i2c comm */ +extern s32 i2c_comm_lock(u8 addr); +extern s32 i2c_comm_unlock(u8 addr); +extern s32 i2c_comm_cancel_alarm(u8 addr); +extern s32 i2c_comm_update_state(u8 addr); +extern s32 i2c_comm_read_state(u8 addr, u8 *state); + +/* control board */ +extern s32 mfcard_module_open(void); +extern void mfcard_module_close(void); +extern int alarm_ctrl(int on_off); +extern int power_ctrl(int on_off); +extern int fpr_press_detect(void); +extern int card_start(void); +extern int card_state(void); +extern int get_card_id(void); +extern s32 door_ctrl(s32 flag); +extern s32 get_door_fb(void); +extern s32 get_pw_jc(void); +extern s32 get_qwz1(void); +extern s32 get_qwz2(void); + +/* monitor */ +extern void monitor_init(void); +extern void monitor(void); +extern void pause_lock_monitor(void); +extern void resume_lock_monitor(void); +extern void pause_all_monitor(void); +extern void resume_all_monitor(void); +//extern void cancel_lock_alarm(void); +extern void cancel_alarm(void); +extern void authorize_open_door(void); +extern void borrow_vector_add(struct passport_data *pass); +extern void borrow_vector_remove(struct passport_data *pass, + struct borrow_ctrl *pcont, + u32 count); +extern u16 *get_current_alarm_info(s32 *flash); +extern void pwd_alarm(void); +extern void setup_alarm(s32 flags); +extern s32 get_alarm_setting(void); +extern s32 get_power_status(void); +extern s32 get_net_status(void); + +/* udisk.cpp */ +extern s32 udisk_remove_detect(void); +extern s32 udisk_insert_detect(struct udisk_info *udisk); + +/* crc.cpp */ +extern u32 crc32_calc(u8 *src, s32 bytes); + +/* net.cpp */ +extern s32 net_module_init(void); +extern void net_module_deinit(void); +extern s32 get_net_link_status(void); +extern s32 get_time_adjust_status(void); +extern void net_monitor(void); +extern void create_heartbeat_packet(void); +extern void create_time_adjust_packet(void); +extern void create_data_packet(u8 cmd, void *data, s32 len); + +#endif \ No newline at end of file diff --git a/src/global_macro.h b/src/global_macro.h new file mode 100644 index 0000000..a27674b --- /dev/null +++ b/src/global_macro.h @@ -0,0 +1,245 @@ +#ifndef GLOBAL_MACRO_H +#define GLOBAL_MACRO_H + +#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0) +#define TIME_BEFORE(a,b) TIME_AFTER(b,a) + +#define WINDOW_CREATE(own,m,x,y,w,h,z,p1,pa,wd) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_WINDOW; \ + own.window.widget = wd; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, NULL, NULL, NULL, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define PICTURE_CREATE(own,m,x,y,w,h,z,p1,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_WINDOW; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, NULL, NULL, NULL, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define PHOTO_CREATE(own,m,x,y,w,h,z) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_PHOTO; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define BUTTON_CREATE(own,m,x,y,w,h,z,p1,p2,p3,p4,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_BUTTON; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, p3, p4, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define LABEL_CREATE(own,m,x,y,w,h,z,f,s,c) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_LABEL; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_font(&own, f, s, c); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define EDIT_CREATE(own,m,x,y,w,h,z,f,s,c,p1,pa,l) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_EDIT; \ + own.edit.word_max = l; \ + own.edit.handle = request_handle(); \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, NULL, NULL, NULL, pa); \ + set_object_font(&own, f, s, c); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define BOX_CREATE(own,m,x,y,w,h,z,f,s,cl,p1,p2,p3,p4,pa,c) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_BOX; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, p3, p4, pa); \ + set_object_font(&own, f, s, cl); \ + memcpy(&own.box.cell, &c, sizeof(c)); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define GRID_CREATE(own,m,x,y,w,h,z,f,s,cl,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_GRID; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_font(&own, f, s, cl); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define RADIO_CREATE(own,m,x,y,w,h,z,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_RADIO; \ + own.radio.handle = request_handle(); \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define CHECK_CREATE(own,m,x,y,w,h,z,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_CHECK; \ + own.check.handle = request_handle(); \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define UPDOWN_CREATE(own,m,x,y,w,h,z,_tw,f,s,c,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_UPDOWN; \ + own.updown.handle = request_handle(); \ + own.updown.tw = _tw; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_font(&own, f, s, c); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + + +#define DRAWGRID_CREATE(own,m,x,y,w,h,z,f,s,c,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_DRAWGRID; \ + own.check.handle = request_handle(); \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_font(&own, f, s, c); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define INDICATOR_CREATE(own,m,x,y,w,h,z,p1,p2,pa) \ +do { \ + memset(&own, 0, sizeof(own)); \ + own.type = SGI_INDICATOR; \ + set_object_pos(&own, x, y, w, h, z); \ + set_object_parent(&own, &m); \ + set_object_image(&own, p1, p2, NULL, NULL, pa); \ + set_object_default_func(&own); \ + m.form.push_back(&own); \ +} while (0) + +#define DRAWGRID_MATRIX(own,r,rh,c,cols) \ +do { \ + own.row = r; \ + own.col = c; \ + own.rowh = rh; \ + memcpy(own.cols, cols, sizeof(cols)); \ +} while (0) + +#define FORM_CREATE(own,w) \ +do { \ + own.wnd = &(w.window); \ + own.redraw = 1; \ + set_object_default_func(&own); \ +} while (0) + +#define FORM_MODULE_RAW(name) \ +struct sgi_form g_##name + +#define FORM_CLASS_RAW(name) \ +g_##name + +#define FORM_NAME_RAW(name) \ +#name + +#define FORM_CREATE_FN_RAW(name) \ +s32 name##_create(void) + +#define FORM_DESTROY_FN_RAW(name) \ +void name##_destroy(void) + +#define FORM_MODULE(name) \ +FORM_MODULE_RAW(name) + +#define FORM_CLASS(name) \ +FORM_CLASS_RAW(name) + +#define FORM_NAME(name) \ +FORM_NAME_RAW(name) + +#define FORM_CREATE_FN(name) \ +FORM_CREATE_FN_RAW(name) + +#define FORM_DESTROY_FN(name) \ +FORM_DESTROY_FN_RAW(name) + +#define FORM_LIST_ITEM(name) \ +{&g_##name, name##_create, name##_destroy, 0} + +#define FORM_DECLARE(name) \ +extern FORM_MODULE(name); \ +extern FORM_CREATE_FN(name); \ +extern FORM_DESTROY_FN(name); + +#define IME_KEY(x,y,w,h) \ +{0,0,x,y,w,h} + +#define CELL(x,y,w,h) \ +{0,0,x,y,w,h} + +#define REAL_PHOTO(s) \ +"/sdcard/log/photo/"#s".png" + +#define DATA_FILE(s) \ +"/sdcard/data/"#s".db" + +#define DBD(s) \ +"/sdcard/data/"#s".db" + +#define DBR(s) \ +"/sdcard/data/"#s".db" + +#define DBL(s) \ +"/sdcard/log/"#s".db" + +#define DBT(s) \ +"/usr/app/"#s".db" + +#define DTC(s) \ +"/sdcard/"#s + +#endif + diff --git a/src/lock.h b/src/lock.h new file mode 100644 index 0000000..78c4f8c --- /dev/null +++ b/src/lock.h @@ -0,0 +1,26 @@ +#ifndef LOCK_H +#define LOCK_H + +#include + +class lock_t +{ +public: + lock_t() + { + pthread_mutexattr_t attr; + + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&m_mutex, &attr); + } + + ~lock_t() {pthread_mutex_destroy(&m_mutex);} + int lock() {return pthread_mutex_lock(&m_mutex);} + int unlock() {return pthread_mutex_unlock(&m_mutex);} + +private: + pthread_mutex_t m_mutex; + +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6d39ca4 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include "global_func.h" + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void quit(int rc) +{ + SDL_Quit(); + exit(rc); +} + +int main(int argc, char **argv) +{ + SDL_Surface *screen; + sigset_t set; + + /* set system env */ + putenv("SDL_MOUSEDRV=TSLIB"); + putenv("SDL_MOUSEDEV=/dev/input/event1"); + + /* mask all signal */ + sigfillset(&set); + if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) { + printf("pthread_sigmask error!\n"); + } + + /* Initialize SDL */ + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0 ) { + fprintf(stderr, + "Couldn't initialize SDL: %s\n", SDL_GetError()); + return(1); + } + + /* Initialize the display, always use hardware palette */ + screen = SDL_SetVideoMode(800, 480, 32, SDL_SWSURFACE); + if ( screen == NULL ) { + fprintf(stderr, "Couldn't set %dx%d video mode: %s\n", + 800, 600, SDL_GetError()); + quit(1); + } + + /* Set the window manager title bar */ + SDL_ShowCursor(0); + SDL_WM_SetCaption("Firearm Manage v1.0", NULL); + + /* Initialize resource(image,font,sound) */ + if (initialize_resource(screen) != 0) { + destroy_resource(); + printf("initialize_resource fail.\n"); + quit(1); + } + + /* fingerprint module open */ + if (fpr_module_init() != 0) { + printf("fpr_module_init fail.\n"); + quit(1); + } + printf("fpr_module_init ok.\n"); + + mfcard_module_open(); + + /* data module init */ + if (data_open() != 0) { + printf("data init fail.\n"); + } + + /* realtime monitor */ + monitor_init(); + + /* net */ + net_module_init(); + + /* main loop */ + //sgi_form_show(&g_fm_main); + sgi_form_show(&g_fm_safecheck); + app_loop(screen); + + /* 程序完蛋 */ + fpr_module_deinit(); + net_module_deinit(); + mfcard_module_close(); + + /* release all resource */ + destroy_resource(); + SDL_Quit(); + + printf("all success.\n"); + + return 0; +} diff --git a/src/monitor.cpp b/src/monitor.cpp new file mode 100644 index 0000000..ca0fa5d --- /dev/null +++ b/src/monitor.cpp @@ -0,0 +1,724 @@ +#include "global_func.h" + +static volatile s32 s_lock_monitor_pause = 0; +static s32 s_lock_monitor_step = 0; +static u32 s_current_alarm = 0; + +struct monitor_control { + s32 enable; + s32 alarm; + u32 cycle; + u32 next_time; +}; + +struct alarm_control { + s16 type; + s16 flash; + time_t time; + u16 content[32]; + u32 lock_addr; + u16 uid[16]; + time_t return_time; +}; + +struct lock_monitor { + s32 enable; + s32 pause; + s32 process; + u32 cycle; + u32 next_time; +}; + +struct door_moinitor { + s32 enable; + s32 ex_enable; + s32 pause; + s32 authorize; + u32 validity; + s32 count; + s32 process; + u32 cycle; + u32 next_time; +}; + +struct power_monitor { + s32 enable; + s32 pause; + s32 count; + s32 process; + u32 cycle; + u32 next_time; +}; + +struct borrow_monitor { + s32 enable; + u32 cycle; +}; + +struct borrow_detail { + s32 process; + u32 next_time; + u16 uid[16]; + time_t return_time; +}; + + +static struct monitor_control s_monitor_control; +static struct door_moinitor s_door_monitor; +static struct lock_monitor s_lock_monitor; +static struct power_monitor s_power_monitor; +static struct borrow_monitor s_borrow_monitor; + +static s32 s_pwd_monitor_enable = 1; + +static s32 s_power_status = POWER_AC; + +static std::vector s_alarm_vec; +static std::vector s_borrow_vec; + +static void monitor_lock(void) +{ + s32 i; + s32 index = s_lock_monitor_step; + s32 found = 0; + u32 current = SDL_GetTicks(); + + if (!s_lock_monitor.enable + || s_lock_monitor.pause + || TIME_BEFORE(current, s_lock_monitor.cycle) + || TIME_BEFORE(current, s_lock_monitor.next_time) + || s_lock_monitor.process) { + return; + } + s_lock_monitor.cycle = SDL_GetTicks() + 1000; + + struct box_info *info = get_box_info(); + for (i = 0; i < BOX_NUMS; ++i) { + if ((info[index].state & 3) == 1) { + found = 1; + break; + } + index = (index + 1) % BOX_NUMS; + } + + s_lock_monitor_step = (index + 1) % BOX_NUMS; + + if (!found) { + return; + } + + if (!s_door_monitor.authorize) { + s32 lock = get_lock_list(); + if (lock > 0) { + printf("lock: %d\n", lock); + i2c_comm_lock(lock); + return; + } + } + + /* */ + if (i2c_comm_update_state(g_box_addr[index]) != 0) { + return; + } + + /* */ + u8 state[4] = {0}; + SDL_Delay(5); + if (i2c_comm_read_state(g_box_addr[index], state) != 0) { + return; + } + printf("lock state: %d\n", state[0]); + + if (state[0] & 0x80) { /* force unlock */ + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = FORCE_UNLOCK; + data.flash = 1; + data.lock_addr = g_box_addr[index]; + time(&data.time); + sgi_sprintf16(data.content, L"枪锁[%03d]被强行打开!", g_box_addr[index]); + s_alarm_vec.push_back(data); + + /* log */ + record_alarm_log(data.content); + + /* */ + s_current_alarm = s_alarm_vec.size() - 1; + + s_lock_monitor.process = 1; + } + else if ((state[0] & 1) == 0) { + if (s_door_monitor.authorize) { + return; + } + + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = FORCE_UNLOCK; + data.flash = 1; + data.lock_addr = g_box_addr[index]; + time(&data.time); + sgi_sprintf16(data.content, L"枪锁[%03d]未锁好!", g_box_addr[index]); + s_alarm_vec.push_back(data); + + /* log */ + record_alarm_log(data.content); + + /* */ + s_current_alarm = s_alarm_vec.size() - 1; + + s_lock_monitor.process = 1; + } +} + +static void monitor_door(void) +{ + s32 state; + s32 qwz = 0; + s32 s; + u32 current = SDL_GetTicks(); + + if (!s_door_monitor.enable + || TIME_BEFORE(current, s_door_monitor.cycle)) { + return; + } + s_door_monitor.cycle = SDL_GetTicks() + 1000; + + state = get_door_fb(); + if (state == -1) { + return; + } + + if (s_door_monitor.pause) { + if (state) { + s_door_monitor.next_time = SDL_GetTicks(); + s_door_monitor.pause = 0; + } + else { + if (TIME_BEFORE(current, s_door_monitor.next_time)) { + return; + } + else { + s_door_monitor.next_time = SDL_GetTicks(); + s_door_monitor.pause = 0; + } + } + } + + if (s_door_monitor.authorize) { + if (TIME_AFTER(current, s_door_monitor.validity)) { + s_door_monitor.authorize = 0; + } + } + + if (s_door_monitor.ex_enable) { + s = get_qwz2(); + if (s == -1) { + return; + } + qwz |= (s & 1) << 1; + + s = get_qwz1(); + if (s == -1) { + return; + } + qwz |= s & 1; + } + else { + qwz = 3; + } + + //printf("authorize2: %d\n", s_door_monitor.authorize); + if (!state || (qwz & 3) != 3) { + if (!s_door_monitor.authorize && !s_door_monitor.process) { + s_door_monitor.count++; + if (s_door_monitor.count < DOOR_MON_COUNT) { + return; + } + + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = FORCE_OPEN_DOOR; + data.flash = 1; + time(&data.time); + sgi_cpw2u(data.content, L"枪柜门异常开启!"); + s_alarm_vec.push_back(data); + + /* log */ + record_alarm_log(data.content); + + /* */ + s_current_alarm = s_alarm_vec.size() - 1; + + s_door_monitor.process = 1; + } + } + else { + if (s_door_monitor.authorize) { + if (state && (qwz & 3) == 3) { + s_door_monitor.authorize = 0; + s_door_monitor.process = 0; + s_door_monitor.count = 0; + } + } + } +#if 0 + printf("door fb: %d\n", get_door_fb()); + printf("pw jc: %d\n", get_pw_jc()); + printf("qwz1: %d\n", get_qwz1()); + printf("qwz2: %d\n", get_qwz2()); +#endif +} + +void monitor_power(void) +{ + u32 current = SDL_GetTicks(); + s32 s; + + if (!s_power_monitor.enable + || TIME_BEFORE(current, s_power_monitor.cycle)) { + return; + } + s_power_monitor.cycle = SDL_GetTicks() + 1000; + + s = get_pw_jc(); + if (s == -1) { + return; + } + + /* 取消报警期间监视市电有无恢复 */ + if (s_power_monitor.pause) { + if (s) { + s_power_monitor.pause = 0; + s_power_monitor.next_time = SDL_GetTicks(); + } + else { + if (TIME_BEFORE(current, s_power_monitor.next_time)) { + return; + } + else { + s_power_monitor.pause = 0; + s_power_monitor.next_time = SDL_GetTicks(); + } + } + } + + if (!s) { + s_power_status = POWER_BATTERY; + if (!s_power_monitor.process) { + s_power_monitor.count++; + if (s_power_monitor.count < POWER_MON_COUNT) { + return; + } + + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = POWER_LOST; + data.flash = 1; + time(&data.time); + sgi_cpw2u(data.content, L"市电供电异常!"); + s_alarm_vec.push_back(data); + + /* log */ + record_alarm_log(data.content); + + /* */ + s_current_alarm = s_alarm_vec.size() - 1; + + s_power_monitor.process = 1; + } + } + else { + s_power_status = POWER_AC; + } +} + +static void monitor_borrow(void) +{ + u32 current = SDL_GetTicks(); + u32 i; + wchar_t buf[16] = {0}; + time_t real_time; + + if (!s_borrow_monitor.enable + || TIME_BEFORE(current, s_borrow_monitor.cycle)) { + return; + } + s_borrow_monitor.cycle = SDL_GetTicks() + 60000; + + time(&real_time); + for (i = 0; i < s_borrow_vec.size(); ++i) { + if (s_borrow_vec[i].process + || TIME_BEFORE(current, s_borrow_vec[i].next_time)) { + continue; + } + + if (real_time > s_borrow_vec[i].return_time) { + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = BORROW_TIMEOUT; + data.flash = 1; + time(&data.time); + sgi_cpu2w(buf, s_borrow_vec[i].uid); + sgi_sprintf16(data.content, L"用户 [%ls] 用枪超时!", buf); + sgi_cp16(data.uid, s_borrow_vec[i].uid); + data.return_time = s_borrow_vec[i].return_time; + s_alarm_vec.push_back(data); + + /* log */ + record_alarm_log(data.content); + + /* */ + s_current_alarm = s_alarm_vec.size() - 1; + + s_borrow_vec[i].process = 1; + } + } +} + +static void cancel_door_alarm(void) +{ + s_door_monitor.next_time = SDL_GetTicks() + REMIT_TIME; + s_door_monitor.authorize = 0; + s_door_monitor.process = 0; + s_door_monitor.count = 0; + s_power_monitor.pause = 1; +} + +static void cancel_power_alarm(void) +{ + s_power_monitor.next_time = SDL_GetTicks() + POWER_REMIT_TIME; + s_power_monitor.process = 0; + s_power_monitor.count = 0; + s_power_monitor.pause = 1; +} + +static void cancel_lock_alarm(u32 addr) +{ + i2c_comm_cancel_alarm(addr); + s_lock_monitor.next_time = SDL_GetTicks() + REMIT_TIME; + s_lock_monitor.process = 0; +} + +static void cancel_borrow_alarm(void) +{ + u32 i; + + for (i = 0; i < s_borrow_vec.size(); ++i) { + if (!s_borrow_vec[i].process) { + continue; + } + + s_borrow_vec[i].next_time = SDL_GetTicks() + BORROW_REMIT_TIME; + s_borrow_vec[i].process = 0; + } +} + +static void borrow_vector_init(void) +{ + u32 i; + u32 size; + struct borrow_detail detail; + + /* */ + s_borrow_vec.clear(); + struct borrow_ctrl *pcont; + struct borrow_ctrl *p; + pcont = (struct borrow_ctrl *)open_r(DBR(borrow), &size); + if (pcont == NULL) { + return; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + if (p->cells[0] || p->cells[1] || p->cells[2] || p->cells[3]) { + memset(&detail, 0, sizeof(struct borrow_detail)); + sgi_cp16(detail.uid, p->uid); + detail.return_time = p->return_time; + s_borrow_vec.push_back(detail); + } + p++; + } + + /* 关闭 */ + close_r(pcont, size); +} + +void monitor_init(void) +{ + memset(&s_monitor_control, 0, sizeof(s_monitor_control)); + memset(&s_door_monitor, 0, sizeof(s_door_monitor)); + memset(&s_power_monitor, 0, sizeof(s_power_monitor)); + memset(&s_borrow_monitor, 0, sizeof(s_borrow_monitor)); + + s_monitor_control.enable = 1; + s_door_monitor.enable = 1; + s_door_monitor.ex_enable = 1; + s_power_monitor.enable = 1; + s_borrow_monitor.enable = 1; + + s_alarm_vec.clear(); + borrow_vector_init(); +} + +void monitor(void) +{ + if (!s_monitor_control.enable) { + return; + } + + monitor_door(); + monitor_lock(); + monitor_power(); + monitor_borrow(); + + if (s_alarm_vec.size() == 0) { + return; + } + + if (!s_monitor_control.alarm) { + sgi_form_show(&FORM_CLASS(fm_alarm)); + s_monitor_control.alarm = 1; + } +} + +void cancel_alarm(void) +{ + u32 i; + + for (i = 0; i < s_alarm_vec.size(); ++i) { + switch (s_alarm_vec[i].type) { + case FORCE_OPEN_DOOR: + cancel_door_alarm(); + break; + + case FORCE_UNLOCK: + cancel_lock_alarm(s_alarm_vec[i].lock_addr); + break; + + case POWER_LOST: + cancel_power_alarm(); + break; + case BORROW_TIMEOUT: + cancel_borrow_alarm(); + break; + + default: + break; + } + } + + alarm_ctrl(ALARM_OFF); + + s_alarm_vec.clear(); + s_monitor_control.alarm = 0; +} + +void pause_lock_monitor(void) +{ + //__sync_lock_test_and_set(&s_lock_monitor_pause, 1); + s_lock_monitor.enable = 0; +} + +void resume_lock_monitor(void) +{ + //__sync_lock_test_and_set(&s_lock_monitor_pause, 0); + s_lock_monitor.enable = 1; +} + +void pause_all_monitor(void) +{ + s_monitor_control.enable = 0; +} + +void resume_all_monitor(void) +{ + s_monitor_control.enable = 1; +} + +void authorize_open_door(void) +{ + s_door_monitor.authorize = 1; + s_door_monitor.validity = SDL_GetTicks() + AUTHORIZE_TIME; + + door_ctrl(DOOR_OPEN); + SDL_Delay(500); + door_ctrl(DOOR_CLOSE); +} + +void borrow_vector_add(struct passport_data *pass) +{ + struct borrow_detail detail; + + memset(&detail, 0, sizeof(struct borrow_detail)); + sgi_cp16(detail.uid, pass->uid); + detail.return_time = pass->return_time; + s_borrow_vec.push_back(detail); +} + +void borrow_vector_remove(struct passport_data *pass, + struct borrow_ctrl *pcont, + u32 count) +{ + u32 i,j; + s32 remove; + s32 change = 0; + struct borrow_ctrl *p; + std::vector temp_vec; + + /* */ + temp_vec.clear(); + for (i = 0; i < s_borrow_vec.size(); ++i) { + if (sgi_ncmp16(s_borrow_vec[i].uid, pass->uid, + COUNTOF(pass->uid)) != 0) { + continue; + } + + p = pcont; + remove = 0; + for (j = 0; j < count; ++j) { + if (sgi_ncmp16(s_borrow_vec[i].uid, p->uid, + COUNTOF(pass->uid)) == 0 + && s_borrow_vec[i].return_time == p->return_time + && p->cells[0] == 0 + && p->cells[1] == 0 + && p->cells[2] == 0 + && p->cells[3] == 0) { + + /* remove this */ + remove = 1; + change = 0; + } + p++; + } + + if (!remove) { + temp_vec.push_back(s_borrow_vec[i]); + } + } + + if (change) { + s_borrow_vec.clear(); + s_borrow_vec = temp_vec; + temp_vec.clear(); + } +} + +u16 *get_current_alarm_info(s32 *flash) +{ + u16 *content; + + if (s_alarm_vec.empty()) { + return NULL; + } + + s_current_alarm %= s_alarm_vec.size(); + printf("alarm: %d, %d, %d\n", s_alarm_vec.size(), s_current_alarm, + s_alarm_vec[s_current_alarm].type); + + *flash = s_alarm_vec[s_current_alarm].flash; + content = s_alarm_vec[s_current_alarm].content; + s_current_alarm++; + + return content; +} + +void pwd_alarm(void) +{ + if (!s_pwd_monitor_enable) { + return; + } + + struct alarm_control data; + memset(&data, 0, sizeof(struct alarm_control)); + data.type = PWD_ERROR; + time(&data.time); + sgi_cpw2u(data.content, L"连续三次输入错误密码!"); + s_alarm_vec.push_back(data); +} + +void setup_alarm(s32 flags) +{ + if (flags & ALARM_DOOR_EN) { + s_door_monitor.enable = 1; + } + else { + s_door_monitor.enable = 0; + } + + if (flags & ALARM_DOOR_EX_EN) { + s_door_monitor.ex_enable = 1; + } + else { + s_door_monitor.ex_enable = 0; + } + + if (flags & ALARM_LOCK_EN) { + s_lock_monitor.pause = 0; + } + else { + s_lock_monitor.pause = 1; + } + + if (flags & ALARM_POWER_EN) { + s_power_monitor.enable = 1; + } + else { + s_power_monitor.enable = 0; + } + + if (flags & ALARM_BORROW_EN) { + s_borrow_monitor.enable = 1; + } + else { + s_borrow_monitor.enable = 0; + } + + if (flags & ALARM_PWD_EN) { + s_pwd_monitor_enable = 1; + } + else { + s_pwd_monitor_enable = 0; + } +} + +s32 get_alarm_setting(void) +{ + s32 flags = 0; + + if (s_door_monitor.enable) { + flags |= ALARM_DOOR_EN; + } + + if (s_door_monitor.ex_enable) { + flags |= ALARM_DOOR_EX_EN; + } + + if (!s_lock_monitor.pause) { + flags |= ALARM_LOCK_EN; + } + + if (s_power_monitor.enable) { + flags |= ALARM_POWER_EN; + } + + if (s_borrow_monitor.enable) { + flags |= ALARM_BORROW_EN; + } + + if (s_pwd_monitor_enable) { + flags |= ALARM_PWD_EN; + } + + return flags; +} + +s32 get_power_status(void) +{ + return get_pw_jc() ? POWER_AC : POWER_BATTERY; +} + +s32 get_net_status(void) +{ + return 0; +} \ No newline at end of file diff --git a/src/net.cpp b/src/net.cpp new file mode 100644 index 0000000..e22ead4 --- /dev/null +++ b/src/net.cpp @@ -0,0 +1,800 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "global_func.h" + +#define SKIP_WS(s) \ +do { \ + while (isspace(*s) && s++); \ +} while (0) + +#define FIND_QT(s) \ +do { \ + while (*s != '=' && s++); \ + s++; \ +} while (0) + +struct packet_head_t { + u32 magic; + u32 crc; + u8 cmd; + u8 sp[3]; + u32 params; + u16 len; + u16 checksum; + u8 data[0]; +}; + +union packet_t { + struct packet_head_t head; + u8 data[512]; +}; + +static std::deque s_idle_deq; +static std::deque s_work_deq; +static u32 s_pool_total_nums = 0; +static lock_t s_pool_lock; +static pthread_t s_work_thread; +static pthread_t s_test_thread; +static char s_server_ip[32] = SERVER_IP; +static int s_server_port = SERVER_PORT; + +static u32 s_net_monitor_cycle = 0; +static u32 s_net_link_cycle = 0; +static u32 s_time_adjust_cycle = 0; +static volatile u32 s_net_down_cycle = 0; +static volatile s32 s_net_link_status = 0; +static volatile s32 s_time_adjust_status = 0; +static volatile s32 s_thread_exit = 0; + +void get_net_config(void) +{ + char buf[1024]; + + FILE *fp = fopen(DTC(net-cfg.txt), "r"); + if (fp == NULL) { + return; + } + + while (fgets(buf, sizeof(buf), fp)) { + char *p = buf; + + SKIP_WS(p); + if (strncmp(p, "ip", 2) == 0) { + FIND_QT(p); + SKIP_WS(p); + char *p1 = strtok(p, "\n"); + strncpy(s_server_ip, p1, sizeof(s_server_ip)); + } + else if (strncmp(p, "port", 4) == 0) { + FIND_QT(p); + SKIP_WS(p); + char *p1 = strtok(p, "\n"); + s_server_port = atoi(p1); + } + } + + fclose(fp); +} + +void net_pool_init(void) +{ + s32 i; + union packet_t *p; + + s_pool_total_nums = 0; + s_idle_deq.clear(); + s_work_deq.clear(); + + /* */ + for (i = 0; i < POOL_INIT_NUMS; ++i) { + p = (union packet_t *)calloc(1, sizeof(union packet_t)); + if (!p) { + return; + } + + s_pool_total_nums++; + s_idle_deq.push_back(p); + } +} + +void net_pool_deinit(void) +{ + u32 i; + + for (i = 0; i < s_work_deq.size(); ++i) { + free(s_work_deq[i]); + } + + for (i = 0; i < s_idle_deq.size(); ++i) { + free(s_idle_deq[i]); + } + + s_work_deq.clear(); + s_idle_deq.clear(); +} + +void net_pool_realloc(void) +{ + s32 i; + union packet_t *p; + + if (s_pool_total_nums > POOL_MAX_NUMS) { + return; + } + + for (i = 0; i < POOL_REALLOC_NUMS; ++i) { + p = (union packet_t *)calloc(1, sizeof(union packet_t)); + if (!p) { + return; + } + + s_pool_total_nums++; + s_idle_deq.push_back(p); + } +} + +void insert_to_idle_deque(union packet_t *packet) +{ + s_pool_lock.lock(); + s_idle_deq.push_back(packet); + s_pool_lock.unlock(); +} + +void insert_to_work_deque(union packet_t *packet) +{ + s_pool_lock.lock(); + s_work_deq.push_back(packet); + s_pool_lock.unlock(); +} + +void push_top_to_work_deque(union packet_t *packet) +{ + s_pool_lock.lock(); + s_work_deq.push_front(packet); + s_pool_lock.unlock(); +} + +union packet_t *get_from_idle_deque(void) +{ + union packet_t *p = NULL; + + s_pool_lock.lock(); + if (s_idle_deq.empty()) { + net_pool_realloc(); + } + + if (!s_idle_deq.empty()) { + p = s_idle_deq.front(); + s_idle_deq.pop_front(); + }; + s_pool_lock.unlock(); + + return p; +} + +union packet_t *get_from_work_deque(void) +{ + union packet_t *p = NULL; + + s_pool_lock.lock(); + if (!s_work_deq.empty()) { + p = s_work_deq.front(); + s_work_deq.pop_front(); + }; + s_pool_lock.unlock(); + + return p; +} + +u32 get_work_deque_count(void) +{ + u32 t; + + s_pool_lock.lock(); + t = s_work_deq.size(); + s_pool_lock.unlock(); + + return t; +} + +void fill_random(u8 *dst, int len) +{ + while (len-- > 0) { + *dst++ = rand() & 0xff; + } +} + +u16 calc_cks(const u8 *src, int len) +{ + u16 cks = 0; + + while (len-- > 0) { + cks += *src++; + } + + return cks; +} + +void mark_to_file(union packet_t *packet) +{ + u32 id; + + switch (packet->head.cmd) { + case CMD_DATA_ALARM: + id = ((struct log_alarm *)(packet->data))->id; + mark_to_alarm_file(id); + break; + + case CMD_DATA_REPORT_BORROW: + id = ((struct log_report *)(packet->data))->id; + mark_to_report_file(id, CMD_DATA_REPORT_BORROW); + break; + + case CMD_DATA_REPORT_RETURN: + id = ((struct log_report *)(packet->data))->id; + mark_to_report_file(id, CMD_DATA_REPORT_RETURN); + break; + + case CMD_DATA_BORROW: + id = ((struct log_borrow *)(packet->data))->id; + mark_to_borrow_file(id, CMD_DATA_BORROW); + break; + + case CMD_DATA_RETURN: + id = ((struct log_borrow *)(packet->data))->id; + mark_to_borrow_file(id, CMD_DATA_RETURN); + break; + + case CMD_DATA_SYSTEM: + id = ((struct log_system *)(packet->data))->id; + mark_to_system_file(id); + break; + + case CMD_DATA_MANAGER: + id = ((struct log_manager *)(packet->data))->id; + mark_to_system_file(id); + break; + + default: + break; + } +} + +s32 apply_packet(union packet_t *packet) +{ + switch (packet->head.cmd) { + case CMD_TIME_ADJUST: + struct tm *remote; + + remote = localtime((time_t *)&packet->head.params); + printf("%d-%02d-%02d %02d:%02d:%02d\n", + remote->tm_year + 1900, remote->tm_mon + 1, + remote->tm_mday, remote->tm_hour, remote->tm_min, + remote->tm_sec); + + /* adjust time */ + if (stime((time_t *)&(packet->head.params)) == 0) { + /* 写入RTC */ + system("hwclock --systohc"); + + __sync_lock_test_and_set(&s_time_adjust_status, 1); + } + break; + + case CMD_HEARTBEAT: + __sync_lock_test_and_set(&s_net_link_status, 1); + __sync_lock_test_and_set(&s_net_down_cycle, SDL_GetTicks()); + break; + + default: + //mark_to_file(packet); + break; + } + + return 0; +} + +SOCKET async_connect(const char *ip, int port) +{ + struct sockaddr_in server; + int flags; + struct timeval tv = {5, 0}; + SOCKET s = -1; + + s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(s == -1) { + goto err; + } + + /* 将连接设置为异步模式 */ + if ((flags = fcntl(s, F_GETFL, 0)) < 0) { + goto err; + } + if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { + goto err; + } + + /* 服务器参数 */ + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(port); + server.sin_addr.s_addr = inet_addr(ip); + + /* 连接至服务器 */ + if (connect(s, (struct sockaddr*)&server, sizeof(server))) { + //printf("errno: %d, %d\n", s, errno); + if (errno != EINPROGRESS) { + goto err; + } + + /* 连接超时检测 */ + fd_set rfds; + fd_set wfds; + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_SET(s, &rfds); + FD_SET(s, &wfds); + if (select(s + 1, &rfds,&wfds, NULL, &tv) <= 0) { + //printf("-----timeout-----\n"); + goto err; + } + + if (FD_ISSET(s, &rfds) && FD_ISSET(s, &wfds)) { + printf("connect fail\n"); + goto err; + } + + if (!FD_ISSET(s, &wfds)) { + printf("invalid socket: %d\n", s); + goto err; + } + } + + /* 将连接设置为同步模式 */ + if ((flags = fcntl(s, F_GETFL, 0)) < 0) { + goto err; + } + if (fcntl(s, F_SETFL, flags & ~O_NONBLOCK) < 0) { + goto err; + } + + /* 设定发送及接收超时时间 */ + tv.tv_sec = 2; + setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv)); + setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)); + + return s; + +err: + if (s != -1) { + close(s); + } + + return -1; +} + +int transmit(union packet_t *tx, union packet_t *rx) +{ + SOCKET s; + s32 len; + + if ((s = async_connect(s_server_ip, s_server_port)) == -1) { + return -1; + } + //printf("async connect: %d\n", s); + + len = sizeof(struct packet_head_t) + tx->head.len; + if (send(s, (char *)tx, len, MSG_NOSIGNAL) < len) { + close(s); + return -1; + } + + len = sizeof(struct packet_head_t); + if (recv(s, (char *)rx, len, MSG_NOSIGNAL) < len) { + close(s); + perror("recv fail: "); + return -1; + } + + u16 cks = calc_cks(rx->data, len - sizeof(u16)); + if (rx->head.magic != NET_MAGIC || cks != rx->head.checksum) { + close(s); + printf("invalid response packet\n"); + return -1; + } + + printf("rx type: %d, 0x%x\n", rx->head.cmd, rx->head.magic); + + apply_packet(rx); + + close(s); + + return 0; + +} + +static void *work_proc(void *arg) +{ + union packet_t *tx; + union packet_t rx; + int err = 0; + + for (;__sync_fetch_and_or(&s_thread_exit, 0) == 0;) { + tx = get_from_work_deque(); + if (tx) { + bzero(&rx, sizeof(union packet_t)); + if (transmit(tx, &rx) == 0) { + insert_to_idle_deque(tx); + err = 0; + } + else { + switch (tx->head.cmd) { + case CMD_HEARTBEAT: + case CMD_TIME_ADJUST: + insert_to_idle_deque(tx); + break; + + default: + insert_to_work_deque(tx); + break; + } + + err++; + if (err == 3) { + __sync_lock_release(&s_net_link_status); + } + } + } + + SDL_Delay(1000); + } + + return NULL; +} + +void create_data_packet(u8 cmd, void *data, s32 len) +{ + union packet_t *p; + u16 *code; + + if (len > (s32)(sizeof(union packet_t) + - sizeof(struct packet_head_t) + - BOX_CODE_LEN)) { + return; + } + + p = get_from_idle_deque(); + if (!p) { + return; + } + + code = get_box_code(); + + bzero(p, sizeof(union packet_t)); + p->head.magic = NET_MAGIC; + p->head.cmd = cmd; + p->head.len = len; + memcpy(p->head.data, data, p->head.len); + memcpy(p->head.data + p->head.len, code, BOX_CODE_LEN); + p->head.len += BOX_CODE_LEN; + p->head.crc = crc32_calc(p->head.data, p->head.len); + p->head.checksum = calc_cks((u8 *)p, sizeof(struct packet_head_t) + - sizeof(u16)); + + insert_to_work_deque(p); +} + +static void create_cmd_packet(u8 cmd) +{ + union packet_t *p; + + p = get_from_idle_deque(); + if (!p) { + return; + } + + bzero(p, sizeof(union packet_t)); + p->head.magic = NET_MAGIC; + p->head.cmd = cmd; + p->head.checksum = calc_cks((u8 *)p, sizeof(struct packet_head_t) + - sizeof(u16)); + + //insert_to_work_deque(p); + push_top_to_work_deque(p); +} + +void create_heartbeat_packet(void) +{ + create_cmd_packet(CMD_HEARTBEAT); +} + +void create_time_adjust_packet(void) +{ + __sync_lock_release(&s_time_adjust_status); + create_cmd_packet(CMD_TIME_ADJUST); +} + +#if 0 +static void *test_proc(void *arg) +{ + union packet_t *p; + int count; + + for (;;) { + if ((count = get_work_deque_count()) < 5) { + p = get_from_idle_deque(); + if (!p) { + continue; + } + + #if 1 + //printf("fill work deque: %d\n", count); + bzero(p, sizeof(union packet_t)); + p->head.magic = NET_MAGIC; + if ((rand() % 10) == 0) { + p->head.cmd = CMD_TIME_ADJUST; + } + else + p->head.cmd = 1; + + //p->head.len = rand() % (sizeof(union packet_t) - sizeof(struct packet_head_t)); + //fill_random(p->head.data, p->head.len); + //p->head.crc = crc32_calc(p->head.data, (int)p->head.len); + //p->head.params = 0; + p->head.checksum = calc_cks((u8 *)p, sizeof(struct packet_head_t) - 2); + + insert_to_work_deque(p); + #endif + //create_heartbeat_packet(); + } + + usleep(10000); + } +} +#endif + +static void collect_from_file(void) +{ + u32 i; + size_t size; + void *pcont; + + /* alarm */ + pcont = sgi_log_open(DBL(alarm), &size); + if (pcont) { + struct log_alarm *p = (struct log_alarm *)pcont; + for (i = 0; i < size / sizeof(struct log_alarm); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_ALARM, p, + sizeof(struct log_alarm)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* report borrow */ + pcont = sgi_log_open(DBL(report-borrow), &size); + if (pcont) { + struct log_report *p = (struct log_report *)pcont; + for (i = 0; i < size / sizeof(struct log_report); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_REPORT_BORROW, p, + sizeof(struct log_report)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* report return */ + pcont = sgi_log_open(DBL(report-back), &size); + if (pcont) { + struct log_report *p = (struct log_report *)pcont; + for (i = 0; i < size / sizeof(struct log_report); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_REPORT_RETURN, p, + sizeof(struct log_report)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* borrow */ + pcont = sgi_log_open(DBL(borrow), &size); + if (pcont) { + struct log_borrow *p = (struct log_borrow *)pcont; + for (i = 0; i < size / sizeof(struct log_borrow); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_BORROW, p, + sizeof(struct log_borrow)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* return */ + pcont = sgi_log_open(DBL(back), &size); + if (pcont) { + struct log_borrow *p = (struct log_borrow *)pcont; + for (i = 0; i < size / sizeof(struct log_borrow); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_RETURN, p, + sizeof(struct log_borrow)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* system */ + pcont = sgi_log_open(DBL(syslog), &size); + if (pcont) { + struct log_system *p = (struct log_system *)pcont; + for (i = 0; i < size / sizeof(struct log_system); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_SYSTEM, p, + sizeof(struct log_system)); + + p++; + } + + sgi_log_close(pcont, size); + } + + /* manager */ + pcont = sgi_log_open(DBL(manager), &size); + if (pcont) { + struct log_manager *p = (struct log_manager *)pcont; + for (i = 0; i < size / sizeof(struct log_manager); ++i) { + if (p->up) { + continue; + } + + create_data_packet(CMD_DATA_SYSTEM, p, + sizeof(struct log_manager)); + + p++; + } + + sgi_log_close(pcont, size); + } +} + +s32 net_module_init(void) +{ + s32 ret; + + get_net_config(); + + printf("ip: %s, port: %d\n", s_server_ip, s_server_port); + + net_pool_init(); + + collect_from_file(); + + printf("work deque: %d\n", get_work_deque_count()); + + ret = pthread_create(&s_work_thread, NULL, work_proc, NULL); + if (ret) { + return -1; + } + +#if 0 + ret = pthread_create(&s_test_thread, NULL, test_proc, NULL); + if (ret) { + return -1; + } +#endif + + return 0; +} + +void net_module_deinit(void) +{ + __sync_lock_test_and_set(&s_thread_exit, 1); + pthread_join(s_work_thread, NULL); + //pthread_join(s_test_thread, NULL); +} + +void net_monitor(void) +{ + u32 current = SDL_GetTicks(); + + if (TIME_BEFORE(current, s_net_monitor_cycle)) { + return; + } + s_net_monitor_cycle = SDL_GetTicks() + NET_MONITOR_CYCLE; + + /* */ + u32 cycle = __sync_fetch_and_or(&s_net_down_cycle, 0) + NET_DOWN_CYCLE; + if (TIME_AFTER(current, cycle)) { + __sync_lock_release(&s_net_link_status); + } + + /* */ + if (TIME_AFTER(current, s_net_link_cycle)) { + s_net_link_cycle = SDL_GetTicks() + NET_LINK_CYCLE; + create_heartbeat_packet(); + } + + /* */ + if (TIME_AFTER(current, s_time_adjust_cycle)) { + s_time_adjust_cycle = SDL_GetTicks() + TIME_ADJUST_CYCLE; + create_time_adjust_packet(); + } +} + +s32 get_net_link_status(void) +{ + return __sync_fetch_and_or(&s_net_link_status, 0); +} + +s32 get_time_adjust_status(void) +{ + return __sync_fetch_and_or(&s_time_adjust_status, 0); +} + + +#if 0 + #include +int main(int argc, char **argv) +{ + s32 success = 0; + s32 err = 0; + + sigset_t set; + sigfillset(&set); + if (pthread_sigmask(SIG_SETMASK, &set, NULL) != 0) { + printf("pthread_sigmask error!\n"); + } + + if (net_module_init() == 0) { + printf("net module setup success\n"); + } + else { + printf("net module setup fail\n"); + } + for(;;) { + //create_heartbeat_packet(); + SDL_Delay(1000); + } + + net_module_deinit(); + + return 0; +} +#endif + diff --git a/src/pinyin.cpp b/src/pinyin.cpp new file mode 100755 index 0000000..805b084 --- /dev/null +++ b/src/pinyin.cpp @@ -0,0 +1,1079 @@ +#include "global_func.h" + +struct _PyIndexType { + wchar_t *syllables; + u16 *final; +}; + +/* code table */ +wchar_t _PyMa_a [] = L"阿啊呵爱安"; +wchar_t _PyMa_ai [] = L"哎爱唉碍哀埃挨矮蔼皑癌艾隘暧呆"; +wchar_t _PyMa_an [] = L"安按暗岸案氨鞍俺胺"; +wchar_t _PyMa_aang [] = L"肮昂盎"; +wchar_t _PyMa_aao [] = L"奥澳傲懊熬袄凹敖翱"; + +wchar_t _PyMa_b [] = L"不把吧爸必"; +wchar_t _PyMa_ba [] = L"八吧把爸罢扒拔霸巴叭芭疤捌笆跋靶坝"; +wchar_t _PyMa_bai [] = L"白百佰柏摆败拜稗"; +wchar_t _PyMa_ban [] = L"扳班办半般搬板伴拌绊版斑扮颁瓣"; +wchar_t _PyMa_bang [] = L"邦帮梆绑榜膀蚌傍棒谤磅镑"; +wchar_t _PyMa_bao [] = L"包宝饱报抱保苞胞褒雹堡豹鲍暴爆剥薄瀑"; +wchar_t _PyMa_bei [] = L"被北倍杯备背卑悲碑贝狈钡惫焙辈"; +wchar_t _PyMa_ben [] = L"本奔苯笨夯"; +wchar_t _PyMa_beng [] = L"崩绷甭迸蹦泵"; +wchar_t _PyMa_bi [] = L"必毕闭鼻比彼笔币避鄙逼庇毖陛毙敝痹蓖弊碧蔽壁臂"; +wchar_t _PyMa_bian [] = L"边编鞭贬扁卞便变遍辨辩辫"; +wchar_t _PyMa_biao [] = L"彪标膘表"; +wchar_t _PyMa_bie [] = L"憋鳖别瘪"; +wchar_t _PyMa_bin [] = L"宾斌彬滨鬓濒摈"; +wchar_t _PyMa_bing [] = L"冰丙并病秉柄炳饼兵"; +wchar_t _PyMa_bo [] = L"拨波玻钵脖菠播伯驳帛泊勃铂舶博渤搏箔膊卜"; +wchar_t _PyMa_bu [] = L"不补哺捕布步怖部埠簿"; + +wchar_t _PyMa_c [] = L"才吃此差错"; +wchar_t _PyMa_ca [] = L"擦嚓"; +wchar_t _PyMa_cai [] = L"猜才菜蔡财材裁采彩睬踩"; +wchar_t _PyMa_can [] = L"参餐残蚕惭惨灿"; +wchar_t _PyMa_cang [] = L"仓沧苍舱藏"; +wchar_t _PyMa_cao [] = L"曹操草嘈槽糙"; +wchar_t _PyMa_ce [] = L"侧厕测策册恻"; +wchar_t _PyMa_ceng [] = L"层蹭曾"; +wchar_t _PyMa_ci [] = L"此次词辞刺慈磁瓷伺祠雌赐疵茨糍"; +wchar_t _PyMa_cong [] = L"囱从匆葱聪丛"; +wchar_t _PyMa_cou [] = L"凑"; +wchar_t _PyMa_cu [] = L"粗促醋簇"; +wchar_t _PyMa_cuan [] = L"蹿窜篡"; +wchar_t _PyMa_cui [] = L"崔催摧脆淬瘁粹翠"; +wchar_t _PyMa_cun [] = L"寸村存"; +wchar_t _PyMa_cuo [] = L"错搓磋撮挫措鹾"; + +wchar_t _PyMa_d [] = L"的地得第多"; +wchar_t _PyMa_da [] = L"大打搭达答瘩"; +wchar_t _PyMa_dai [] = L"呆歹傣代带待怠殆贷袋逮戴"; +wchar_t _PyMa_dan [] = L"但单担淡耽蛋旦丹弹胆掸诞惮郸氮"; +wchar_t _PyMa_dang [] = L"当挡党荡档"; +wchar_t _PyMa_dao [] = L"道到倒导盗刀岛捣稻蹈悼祷"; +wchar_t _PyMa_de [] = L"的地得德"; +wchar_t _PyMa_deng [] = L"灯等登蹬邓凳瞪"; +wchar_t _PyMa_di [] = L"第地弟低底抵堤滴狄迪敌涤笛嫡帝递缔蒂"; +wchar_t _PyMa_dian [] = L"点电店典掂惦甸垫淀奠颠碘佃殿滇靛"; +wchar_t _PyMa_diao [] = L"掉钓刁叼凋碉雕吊"; +wchar_t _PyMa_die [] = L"爹跌叠蝶谍碟迭"; +wchar_t _PyMa_ding [] = L"顶定订丁钉叮盯鼎锭"; +wchar_t _PyMa_diu [] = L"丢"; +wchar_t _PyMa_dong [] = L"动东冬懂冻洞董侗恫栋"; +wchar_t _PyMa_dou [] = L"都豆斗抖陡逗兜痘"; +wchar_t _PyMa_du [] = L"杜读独肚度督毒犊堵赌睹妒渡镀"; +wchar_t _PyMa_duan [] = L"端短段断缎锻"; +wchar_t _PyMa_dui [] = L"对堆队兑"; +wchar_t _PyMa_dun [] = L"吨敦墩蹲盾钝顿遁"; +wchar_t _PyMa_duo [] = L"多哆夺掇朵垛躲剁堕舵惰跺"; + +wchar_t _PyMa_e [] = L"二饿鹅恶额俄讹娥峨蛾遏厄扼鄂"; +wchar_t _PyMa_en [] = L"恩嗯"; +wchar_t _PyMa_er [] = L"二儿而尔耳洱饵贰"; + +wchar_t _PyMa_f [] = L"发否方放法"; +wchar_t _PyMa_fa [] = L"法发乏罚伐阀筏珐"; +wchar_t _PyMa_fan [] = L"反饭翻烦返繁帆番藩凡矾钒樊犯泛范贩"; +wchar_t _PyMa_fang [] = L"方放坊芳防妨房肪仿访纺"; +wchar_t _PyMa_fei [] = L"飞非啡菲费肥匪诽吠废沸肺"; +wchar_t _PyMa_fen [] = L"分份吩纷奋愤芬氛酚坟汾焚粉忿粪"; +wchar_t _PyMa_feng [] = L"峰锋丰风枫封疯烽蜂冯逢缝讽凤奉"; +wchar_t _PyMa_fo [] = L"佛"; +wchar_t _PyMa_fou [] = L"否"; +wchar_t _PyMa_fu [] = L"服复幅付夫妇赴副肤父符府附咐伏扶福敷弗拂俘氟浮涪袱辐抚甫斧俯釜辅腑腐讣负阜傅孵富赋缚腹覆"; + +wchar_t _PyMa_g [] = L"给该个广郭"; +wchar_t _PyMa_ga [] = L"嘎噶尬"; +wchar_t _PyMa_gai [] = L"该改概盖钙溉"; +wchar_t _PyMa_gan [] = L"干甘杆柑肝赶敢感赣竿秆尴"; +wchar_t _PyMa_gang [] = L"冈刚岗纲肛缸钢港杠"; +wchar_t _PyMa_gao [] = L"皋羔高膏篙糕搞稿镐告"; +wchar_t _PyMa_ge [] = L"个各格哥咯胳鸽割歌革葛阁搁隔戈疙铬"; +wchar_t _PyMa_gei [] = L"给"; +wchar_t _PyMa_gen [] = L"根跟"; +wchar_t _PyMa_geng [] = L"更庚耕羹埂耿梗"; +wchar_t _PyMa_gong [] = L"公共工弓功攻供宫恭躬龚巩汞拱贡"; +wchar_t _PyMa_gou [] = L"勾沟购够构钩狗苟垢"; +wchar_t _PyMa_gu [] = L"故顾估姑古菇固咕孤沽辜箍谷股骨蛊鼓雇"; +wchar_t _PyMa_gua [] = L"挂瓜刮剐寡褂"; +wchar_t _PyMa_guai [] = L"怪乖拐"; +wchar_t _PyMa_guan [] = L"关惯观管馆官冠棺贯灌罐"; +wchar_t _PyMa_guang[] = L"光广逛"; +wchar_t _PyMa_gui [] = L"归规桂贵瑰闺诡跪轨癸硅龟鬼刽圭柜"; +wchar_t _PyMa_gun [] = L"辊滚棍"; +wchar_t _PyMa_guo [] = L"国过郭锅果裹"; + +wchar_t _PyMa_h [] = L"哈呵嘿和好"; +wchar_t _PyMa_ha [] = L"哈蛤"; +wchar_t _PyMa_hai [] = L"孩海害亥骇氦骸"; +wchar_t _PyMa_han [] = L"汉汗韩含寒函涵捍憾撼罕喊酣憨旱悍焊翰邯"; +wchar_t _PyMa_hang [] = L"杭航行"; +wchar_t _PyMa_hao [] = L"好号毫豪嚎壕郝浩耗"; +wchar_t _PyMa_he [] = L"和何河喝合盒呵核贺禾阂荷涸菏褐赫鹤"; +wchar_t _PyMa_hei [] = L"黑嘿"; +wchar_t _PyMa_hen [] = L"很狠恨痕"; +wchar_t _PyMa_heng [] = L"哼横亨恒衡"; +wchar_t _PyMa_hong [] = L"红哄洪烘宏鸿轰虹弘"; +wchar_t _PyMa_hou [] = L"后厚候喉猴吼侯"; +wchar_t _PyMa_hu [] = L"乎呼忽胡护弧狐壶湖葫瑚糊蝴虎唬互户沪"; +wchar_t _PyMa_hua [] = L"花话华化哗滑猾划画"; +wchar_t _PyMa_huai [] = L"怀坏淮徊槐"; +wchar_t _PyMa_huan [] = L"欢还环患换缓幻焕痪唤涣宦桓豢"; +wchar_t _PyMa_huang[] = L"黄荒慌皇凰惶煌蝗磺簧恍晃谎幌"; +wchar_t _PyMa_hui [] = L"会恢回灰慧挥辉徽汇悔诲绘卉烩贿晦讳蛔秽惠毁"; +wchar_t _PyMa_hun [] = L"昏婚混荤浑魂"; +wchar_t _PyMa_huo [] = L"或货活火伙获祸惑霍豁"; + +wchar_t _PyMa_j [] = L"九今及几家"; +wchar_t _PyMa_ji [] = L"己计记极基纪技际积继几及击急寂既寄讥饥圾机肌鸡迹姬绩缉畸箕稽激吉汲级即疾棘集嫉辑籍挤脊伎妓忌剂季济悸祭蓟冀藉"; +wchar_t _PyMa_jia [] = L"家加夹价驾佳假嘉颊甲贾钾架嫁枷稼荚挟"; +wchar_t _PyMa_jian [] = L"见件间建简渐减奸尖坚歼肩艰兼监缄煎拣俭柬茧捡剪检硷碱饯剑荐贱健涧舰溅践笺鉴键箭"; +wchar_t _PyMa_jiang[] = L"江将浆姜讲奖降蒋匠疆桨僵酱"; +wchar_t _PyMa_jiao [] = L"交觉叫郊较教饺娇浇骄胶椒角焦蕉礁狡绞矫脚铰搅剿缴轿窖酵嚼"; +wchar_t _PyMa_jie [] = L"阶借姐街介结节解界接皆届揭劫杰洁捷睫截竭戒秸芥疥诫"; +wchar_t _PyMa_jin [] = L"今近进斤紧仅尽巾劲津金筋襟谨锦晋浸烬禁靳"; +wchar_t _PyMa_jing [] = L"京经净警景惊精睛竞竟敬井晶境静镜颈径痉茎靖兢鲸粳荆"; +wchar_t _PyMa_jiong[] = L"炯窘"; +wchar_t _PyMa_jiu [] = L"九就久酒旧究舅纠救揪咎疚灸玖韭臼厩"; +wchar_t _PyMa_ju [] = L"据句局拒距巨聚具桔菊拘剧驹居举鞠咀沮矩炬俱惧锯踞狙疽"; +wchar_t _PyMa_juan [] = L"娟捐鹃卷倦绢眷"; +wchar_t _PyMa_jue [] = L"绝觉决抉诀倔掘爵撅攫"; +wchar_t _PyMa_jun [] = L"军君均钧竣俊峻骏菌郡浚"; + +wchar_t _PyMa_k [] = L"开可快看况"; +wchar_t _PyMa_ka [] = L"卡咖喀咔"; +wchar_t _PyMa_kai [] = L"开揩凯慨楷忾"; +wchar_t _PyMa_kan [] = L"看砍刊坎勘堪槛侃瞰"; +wchar_t _PyMa_kang [] = L"康慷糠扛亢抗炕伉"; +wchar_t _PyMa_kao [] = L"靠考拷烤犒"; +wchar_t _PyMa_ke [] = L"客科可克刻渴课棵颗壳恪咳坷苛珂柯嗑磕瞌"; +wchar_t _PyMa_ken [] = L"肯垦恳啃"; +wchar_t _PyMa_keng [] = L"吭坑铿"; +wchar_t _PyMa_kong [] = L"空孔恐控崆倥"; +wchar_t _PyMa_kou [] = L"口扣抠寇叩"; +wchar_t _PyMa_ku [] = L"哭库苦裤酷枯窟骷绔"; +wchar_t _PyMa_kua [] = L"夸垮挎胯跨"; +wchar_t _PyMa_kuai [] = L"块快侩筷会脍"; +wchar_t _PyMa_kuan [] = L"宽款"; +wchar_t _PyMa_kuang[] = L"框况狂邝矿筐旷眶诳诓匡"; +wchar_t _PyMa_kui [] = L"亏馈窥愧盔溃奎葵魁傀岿"; +wchar_t _PyMa_kun [] = L"坤昆捆困琨"; +wchar_t _PyMa_kuo [] = L"扩括阔廓"; + +wchar_t _PyMa_l [] = L"了来拉老六"; +wchar_t _PyMa_la [] = L"啦拉垃喇腊蜡辣"; +wchar_t _PyMa_lai [] = L"来莱赖"; +wchar_t _PyMa_lan [] = L"兰篮蓝懒拦栏览揽烂婪阑谰澜缆滥"; +wchar_t _PyMa_lang [] = L"郎狼廊琅榔朗浪"; +wchar_t _PyMa_lao [] = L"老捞劳牢佬姥涝烙酪"; +wchar_t _PyMa_le [] = L"了乐勒"; +wchar_t _PyMa_lei [] = L"类泪累雷蕾镭磊擂肋垒儡"; +wchar_t _PyMa_leng [] = L"棱楞冷"; +wchar_t _PyMa_li [] = L"李理里立利丽例离力莉梨粒厘漓璃黎篱礼哩鲤历厉吏励沥隶俐荔栗砾犁傈痢狸"; +wchar_t _PyMa_lian [] = L"连联脸怜练恋炼帘涟莲廉镰敛链"; +wchar_t _PyMa_liang[] = L"两俩良凉梁量亮辆谅粮粱晾"; +wchar_t _PyMa_liao [] = L"了潦辽廖疗聊僚寥撩燎镣料撂"; +wchar_t _PyMa_lie [] = L"列劣烈猎裂咧"; +wchar_t _PyMa_lin [] = L"林临邻淋琳霖赁凛吝拎磷鳞"; +wchar_t _PyMa_ling [] = L"另令零龄领铃伶灵岭凌菱玲陵羚"; +wchar_t _PyMa_liu [] = L"六刘流留溜柳榴硫馏瘤琉"; +wchar_t _PyMa_long [] = L"龙笼隆聋垄窿陇拢咙"; +wchar_t _PyMa_lou [] = L"搂楼篓陋娄漏髅"; +wchar_t _PyMa_lu [] = L"卢录鲁陆露路庐炉颅芦鹿卤赂虏掳禄碌戮潞麓"; +wchar_t _PyMa_luan [] = L"乱孪峦挛滦卵"; +wchar_t _PyMa_lue [] = L"略掠"; +wchar_t _PyMa_lun [] = L"抡论轮仑伦沦纶"; +wchar_t _PyMa_luo [] = L"罗萝洛络锣箩落骡螺逻裸骆"; +wchar_t _PyMa_lv [] = L"率吕侣绿旅律虑滤驴铝屡缕履氯"; + +wchar_t _PyMa_m [] = L"妈吗嘛没们"; +wchar_t _PyMa_ma [] = L"妈吗嘛麻马玛码蚂骂"; +wchar_t _PyMa_mai [] = L"买卖迈麦埋脉"; +wchar_t _PyMa_man [] = L"蛮馒瞒满曼谩慢漫蔓"; +wchar_t _PyMa_mang [] = L"忙芒盲茫莽氓"; +wchar_t _PyMa_mao [] = L"猫毛矛茅锚卯铆茂冒贸帽貌"; +wchar_t _PyMa_me [] = L"么"; +wchar_t _PyMa_mei [] = L"没每妹美枚玫眉梅媒煤酶霉镁昧媚寐"; +wchar_t _PyMa_men [] = L"们门闷懑"; +wchar_t _PyMa_meng [] = L"梦猛萌孟盟檬蒙锰"; +wchar_t _PyMa_mi [] = L"秘密蜜米迷谜觅泌糜靡眯醚弥幂"; +wchar_t _PyMa_mian [] = L"面免勉眠绵棉娩冕缅"; +wchar_t _PyMa_miao [] = L"妙秒描苗瞄庙渺藐"; +wchar_t _PyMa_mie [] = L"灭乜蔑"; +wchar_t _PyMa_min [] = L"民敏皿抿闽悯玟"; +wchar_t _PyMa_ming [] = L"明名命鸣铭螟冥"; +wchar_t _PyMa_miu [] = L"谬缪"; +wchar_t _PyMa_mo [] = L"莫摸模默抹摩磨蘑魔寞末膜貉墨摹沫陌漠"; +wchar_t _PyMa_mou [] = L"牟谋某眸"; +wchar_t _PyMa_mu [] = L"母木目牡亩幕睦慕牧姆拇募墓暮穆"; + +wchar_t _PyMa_n [] = L"你哪那能年"; +wchar_t _PyMa_na [] = L"哪那拿纳娜钠呐"; +wchar_t _PyMa_nai [] = L"乃奶奈耐氖"; +wchar_t _PyMa_nan [] = L"男南难喃楠"; +wchar_t _PyMa_nang [] = L"囊"; +wchar_t _PyMa_nao [] = L"挠恼脑闹淖"; +wchar_t _PyMa_ne [] = L"呢"; +wchar_t _PyMa_nei [] = L"内那馁"; +wchar_t _PyMa_nen [] = L"嫩恁"; +wchar_t _PyMa_neng [] = L"能"; +wchar_t _PyMa_ni [] = L"你拟妮尼泥倪霓逆匿溺腻"; +wchar_t _PyMa_nian [] = L"年念捻拈撵碾蔫"; +wchar_t _PyMa_niang[] = L"娘酿"; +wchar_t _PyMa_niao [] = L"鸟尿"; +wchar_t _PyMa_nie [] = L"捏聂镊涅啮镍孽"; +wchar_t _PyMa_nin [] = L"您"; +wchar_t _PyMa_ning [] = L"宁拧狞凝柠泞"; +wchar_t _PyMa_niu [] = L"牛扭纽钮"; +wchar_t _PyMa_nong [] = L"弄农浓脓"; +wchar_t _PyMa_nu [] = L"怒努奴弩"; +wchar_t _PyMa_nuan [] = L"暖"; +wchar_t _PyMa_nue [] = L"疟虐谑"; +wchar_t _PyMa_nuo [] = L"挪诺懦糯"; +wchar_t _PyMa_nv [] = L"女"; + +wchar_t _PyMa_o [] = L"哦噢"; +wchar_t _PyMa_ou [] = L"欧殴鸥呕偶藕沤区"; + +wchar_t _PyMa_p [] = L"怕拼彭潘朋"; +wchar_t _PyMa_pa [] = L"怕趴啪爬耙琶帕"; +wchar_t _PyMa_pai [] = L"拍徘排牌派湃"; +wchar_t _PyMa_pan [] = L"潘攀盘磐判叛盼畔"; +wchar_t _PyMa_pang [] = L"乓庞旁耪胖"; +wchar_t _PyMa_pao [] = L"抛刨咆炮袍跑泡"; +wchar_t _PyMa_pei [] = L"胚陪培赔佩配裴沛呸"; +wchar_t _PyMa_pen [] = L"喷盆"; +wchar_t _PyMa_peng [] = L"彭抨朋碰砰鹏烹棚硼蓬澎篷膨捧"; +wchar_t _PyMa_pi [] = L"皮批啤披脾疲劈霹僻譬毗琵匹辟坯痞屁砒"; +wchar_t _PyMa_pian [] = L"片偏篇骗"; +wchar_t _PyMa_piao [] = L"漂飘瓢票"; +wchar_t _PyMa_pie [] = L"撇瞥"; +wchar_t _PyMa_pin [] = L"拼贫频品聘"; +wchar_t _PyMa_ping [] = L"乒平评凭坪苹屏瓶萍"; +wchar_t _PyMa_po [] = L"坡泼颇婆迫破粕魄"; +wchar_t _PyMa_pou [] = L"剖"; +wchar_t _PyMa_pu [] = L"扑铺仆普谱葡莆菩脯蒲朴圃埔浦曝"; + +wchar_t _PyMa_q [] = L"七其请去却"; +wchar_t _PyMa_qi [] = L"七其齐气起妻企骑器岂期欺棋旗柒凄栖戚漆祁奇歧祈脐崎畦沏乞启讫迄弃汽泣契砌"; +wchar_t _PyMa_qia [] = L"掐恰洽"; +wchar_t _PyMa_qian [] = L"千前钱欠谦签潜浅嵌歉仟扦迁钎牵铅钳乾黔遣谴堑"; +wchar_t _PyMa_qiang[] = L"强墙抢枪蔷羌腔呛"; +wchar_t _PyMa_qiao [] = L"巧悄敲瞧桥窍翘橇乔侨俏峭锹撬鞘"; +wchar_t _PyMa_qie [] = L"切茄且怯窃"; +wchar_t _PyMa_qin [] = L"亲侵钦芹秦琴禽勤擒寝沁"; +wchar_t _PyMa_qing [] = L"请青清情晴轻倾庆卿氰擎顷氢"; +wchar_t _PyMa_qiong[] = L"穷琼"; +wchar_t _PyMa_qiu [] = L"求球邱秋囚泅酋丘"; +wchar_t _PyMa_qu [] = L"去区趣取曲躯趋娶驱屈蛆渠龋"; +wchar_t _PyMa_quan [] = L"全权圈劝泉拳痊醛颧犬券"; +wchar_t _PyMa_que [] = L"却确缺雀鹊瘸炔榷"; +wchar_t _PyMa_qun [] = L"裙群"; + +wchar_t _PyMa_r [] = L"然人日如让"; +wchar_t _PyMa_ran [] = L"然燃冉染"; +wchar_t _PyMa_rang [] = L"让嚷瓤壤攘"; +wchar_t _PyMa_rao [] = L"饶扰绕"; +wchar_t _PyMa_re [] = L"惹热"; +wchar_t _PyMa_ren [] = L"人认任仁壬忍刃纫妊韧"; +wchar_t _PyMa_reng [] = L"扔仍"; +wchar_t _PyMa_ri [] = L"日"; +wchar_t _PyMa_rong [] = L"荣容溶蓉融熔戎绒茸冗"; +wchar_t _PyMa_rou [] = L"柔揉肉"; +wchar_t _PyMa_ru [] = L"如入茹乳辱褥儒孺蠕汝"; +wchar_t _PyMa_ruan [] = L"软阮"; +wchar_t _PyMa_rui [] = L"锐瑞蕊"; +wchar_t _PyMa_run [] = L"闰润"; +wchar_t _PyMa_ruo [] = L"若弱"; + +wchar_t _PyMa_s [] = L"是上三什谁"; +wchar_t _PyMa_sa [] = L"撒洒萨"; +wchar_t _PyMa_sai [] = L"塞腮鳃赛"; +wchar_t _PyMa_san [] = L"三叁伞散"; +wchar_t _PyMa_sang [] = L"桑嗓丧"; +wchar_t _PyMa_sao [] = L"搔骚扫嫂臊"; +wchar_t _PyMa_se [] = L"色涩啬瑟"; +wchar_t _PyMa_sen [] = L"森"; +wchar_t _PyMa_seng [] = L"僧"; +wchar_t _PyMa_si [] = L"四司私思斯丝嘶撕死巳寺伺饲嗣肆"; +wchar_t _PyMa_song [] = L"送松怂耸讼宋诵颂嵩"; +wchar_t _PyMa_sou [] = L"嗽搜艘擞"; +wchar_t _PyMa_su [] = L"速诉苏酥俗肃素粟塑溯僳"; +wchar_t _PyMa_suan [] = L"酸蒜算"; +wchar_t _PyMa_sui [] = L"虽岁随碎穗遂髓绥隋祟隧"; +wchar_t _PyMa_sun [] = L"孙损笋"; +wchar_t _PyMa_suo [] = L"所锁缩索唆琐梭蓑"; + +wchar_t _PyMa_t [] = L"她他它天太"; +wchar_t _PyMa_ta [] = L"她他它塌塔獭挞踏蹋"; +wchar_t _PyMa_tai [] = L"太胎台抬态泰苔汰酞"; +wchar_t _PyMa_tan [] = L"叹探谈谭摊滩瘫贪炭毯坛坍痰潭檀坦袒碳"; +wchar_t _PyMa_tang [] = L"倘趟糖汤唐堂棠塘搪膛淌躺烫"; +wchar_t _PyMa_tao [] = L"讨萄涛桃绦套掏滔逃陶淘"; +wchar_t _PyMa_te [] = L"特"; +wchar_t _PyMa_teng [] = L"疼腾誊藤"; +wchar_t _PyMa_ti [] = L"剔梯锑踢啼提题蹄体屉剃涕惕替嚏"; +wchar_t _PyMa_tian [] = L"天添田恬甜填腆舔"; +wchar_t _PyMa_tiao [] = L"调挑条迢眺跳"; +wchar_t _PyMa_tie [] = L"贴铁帖"; +wchar_t _PyMa_ting [] = L"厅汀听烃廷亭庭停挺艇"; +wchar_t _PyMa_tong [] = L"通同彤桐铜童酮瞳统捅桶筒痛"; +wchar_t _PyMa_tou [] = L"偷头投透"; +wchar_t _PyMa_tu [] = L"凸秃突图徒涂途屠土吐兔"; +wchar_t _PyMa_tuan [] = L"湍团"; +wchar_t _PyMa_tui [] = L"推颓腿退蜕褪"; +wchar_t _PyMa_tun [] = L"囤吞屯臀"; +wchar_t _PyMa_tuo [] = L"托拖脱驮陀驼鸵妥椭拓唾"; + +wchar_t _PyMa_w [] = L"我五无吴为"; +wchar_t _PyMa_wa [] = L"哇娃挖洼蛙瓦袜"; +wchar_t _PyMa_wai [] = L"外歪"; +wchar_t _PyMa_wan [] = L"弯湾豌丸完玩顽烷宛挽晚婉惋皖碗万腕纨"; +wchar_t _PyMa_wang [] = L"往王网望忘汪亡枉妄旺"; +wchar_t _PyMa_wei [] = L"为危位喂威伟唯委维味韦围谓微违魏潍慰伪尾纬苇萎卫未畏胃尉渭惟桅蔚巍韪"; +wchar_t _PyMa_wen [] = L"文温闻问稳吻纹蚊紊瘟"; +wchar_t _PyMa_weng [] = L"翁嗡瓮"; +wchar_t _PyMa_wo [] = L"我卧握挝涡窝蜗沃斡龌"; +wchar_t _PyMa_wu [] = L"五午吴误无务晤武侮巫屋污诬钨毋吾芜梧伍呜乌坞捂舞勿戊物悟雾"; + +wchar_t _PyMa_x [] = L"下象想兴小"; +wchar_t _PyMa_xi [] = L"西细系息熄席牺惜吸悉戏洗习喜隙媳希昔溪夕汐析矽烯硒晰犀稀嘻膝袭锡熙檄"; +wchar_t _PyMa_xia [] = L"下吓夏虾瞎匣侠峡狭暇辖霞"; +wchar_t _PyMa_xian [] = L"现先县线限献显险鲜嫌咸纤掀锨闲弦贤涎舷衔宪陷馅仙羡腺铣"; +wchar_t _PyMa_xiang[] = L"想象相项箱向像香响乡详祥厢巷翔湘享镶橡襄"; +wchar_t _PyMa_xiao [] = L"小笑效肖消校销宵晓萧硝霄孝哮啸嚣淆"; +wchar_t _PyMa_xie [] = L"些写谢歇械斜携鞋协卸邪胁谐泄泻屑蝎懈蟹楔"; +wchar_t _PyMa_xin [] = L"心新薪信辛欣芯锌衅忻"; +wchar_t _PyMa_xing [] = L"行兴姓性形型刑幸星醒杏惺猩腥邢"; +wchar_t _PyMa_xiong[] = L"凶兄匈汹胸雄熊"; +wchar_t _PyMa_xiu [] = L"休修秀绣袖羞朽锈嗅宿"; +wchar_t _PyMa_xu [] = L"徐许须需续虚婿嘘吁绪旭序叙戌墟恤酗絮蓄"; +wchar_t _PyMa_xuan [] = L"选宣喧旋玄轩悬绚癣眩"; +wchar_t _PyMa_xue [] = L"学雪血削穴薛靴"; +wchar_t _PyMa_xun [] = L"讯迅寻巡旬循勋熏驯询训汛逊殉"; + +wchar_t _PyMa_y [] = L"一已呀也与"; +wchar_t _PyMa_ya [] = L"亚呀压牙涯哑雅讶押崖丫鸦鸭芽蚜衙"; +wchar_t _PyMa_yan [] = L"验言烟眼沿严掩颜淹咽燕研延岩宴艳演厌盐炎阎蜒奄彦砚唁谚焰雁衍焉堰阉"; +wchar_t _PyMa_yang [] = L"样阳杨央洋仰养秧漾扬羊佯氧痒鸯疡殃"; +wchar_t _PyMa_yao [] = L"要钥姚摇遥药耀腰邀咬谣侥妖尧窑瑶舀"; +wchar_t _PyMa_ye [] = L"也爷页夜冶液野业叶噎椰曳掖腋耶"; +wchar_t _PyMa_yi [] = L"一以已亿医益谊亦依译伊衣铱壹揖仪夷沂宜姨胰移遗颐疑彝乙矣蚁倚椅义亿忆艺议亦屹异役抑译邑易绎诣疫益谊翌逸意溢肄裔毅翼臆"; +wchar_t _PyMa_yin [] = L"因音姻银引饮阴茵印吟尹隐荫殷淫寅"; +wchar_t _PyMa_ying [] = L"应硬迎英影营映鹰盈荧莹樱婴蝇萤缨赢颖"; +wchar_t _PyMa_yo [] = L"哟"; +wchar_t _PyMa_yong [] = L"用永拥勇咏佣泳涌恿雍臃蛹踊庸痈"; +wchar_t _PyMa_you [] = L"又有优由邮忧幽悠右友诱犹油游酉幼佑尤釉铀"; +wchar_t _PyMa_yu [] = L"与于欲语羽雨玉遇预鱼愈喻寓予余榆誉俞娱渔隅愉逾愚虞舆宇屿禹驭芋育郁狱峪浴域盂淤渝御裕迂豫"; +wchar_t _PyMa_yuan [] = L"元员园远圆愿原院袁冤渊援缘源怨垣猿辕苑鸳"; +wchar_t _PyMa_yue [] = L"约月岳越阅悦跃粤曰"; +wchar_t _PyMa_yun [] = L"云匀郧耘允陨孕运晕酝韵蕴"; + +wchar_t _PyMa_z [] = L"在再怎知则"; +wchar_t _PyMa_za [] = L"匝杂砸咋"; +wchar_t _PyMa_zai [] = L"再在灾载仔栽宰哉"; +wchar_t _PyMa_zan [] = L"咱攒暂赞"; +wchar_t _PyMa_zang [] = L"赃脏葬藏"; +wchar_t _PyMa_zao [] = L"早造噪燥躁澡藻遭糟皂凿枣蚤灶"; +wchar_t _PyMa_ze [] = L"则择泽责"; +wchar_t _PyMa_zei [] = L"è´¼"; +wchar_t _PyMa_zen [] = L"怎"; +wchar_t _PyMa_zeng [] = L"增赠憎"; +wchar_t _PyMa_zi [] = L"子自字资紫咨姿孜兹滋渍籽淄滓"; +wchar_t _PyMa_zong [] = L"总纵宗踪综棕鬃"; +wchar_t _PyMa_zou [] = L"走邹奏揍"; +wchar_t _PyMa_zu [] = L"足组祖租阻族卒诅"; +wchar_t _PyMa_zuan [] = L"钻赚纂"; +wchar_t _PyMa_zui [] = L"最嘴罪醉"; +wchar_t _PyMa_zun [] = L"尊遵"; +wchar_t _PyMa_zuo [] = L"昨做左佐作坐座"; +wchar_t _PyMa_zz [] = L",。!?、;:“”‘’()…#¥%【】《》『』~◎×-+÷=§"; + +wchar_t _PyMa_cha [] = L"插察查茶差叉茬搽碴岔诧刹"; +wchar_t _PyMa_chai [] = L"拆柴差豺"; +wchar_t _PyMa_chan [] = L"产缠掺搀谗馋蝉铲阐婵颤"; +wchar_t _PyMa_chang [] = L"长常唱厂场昌尝偿猖肠敞畅倡"; +wchar_t _PyMa_chao [] = L"抄钞吵炒超巢朝嘲潮绰"; +wchar_t _PyMa_che [] = L"车扯彻掣撤澈"; +wchar_t _PyMa_chen [] = L"郴尘臣忱沉辰陈晨衬趁"; +wchar_t _PyMa_cheng [] = L"称撑成呈承诚城乘惩程澄橙逞骋秤"; +wchar_t _PyMa_chi [] = L"吃痴弛池驰迟持尺侈齿耻斥赤炽翅"; +wchar_t _PyMa_chong [] = L"重充冲虫崇宠铳"; +wchar_t _PyMa_chou [] = L"抽仇绸畴愁稠筹酬踌丑瞅臭"; +wchar_t _PyMa_chu [] = L"处出初除厨楚触锄础雏橱躇储搐矗畜滁"; +wchar_t _PyMa_chuai [] = L"揣踹"; +wchar_t _PyMa_chuan [] = L"穿传串船川椽喘"; +wchar_t _PyMa_chuang[] = L"闯窗床创疮"; +wchar_t _PyMa_chui [] = L"吹炊垂捶锤陲"; +wchar_t _PyMa_chun [] = L"春椿纯唇淳醇蠢"; +wchar_t _PyMa_chuo [] = L"戳绰辍"; +wchar_t _PyMa_sha [] = L"杀沙纱砂莎傻啥煞厦"; +wchar_t _PyMa_shai [] = L"筛晒"; +wchar_t _PyMa_shan [] = L"山衫闪陕删杉珊煽汕苫扇善缮擅膳赡栅"; +wchar_t _PyMa_shang [] = L"上尚伤商墒裳晌赏"; +wchar_t _PyMa_shao [] = L"少捎梢烧稍勺芍韶邵绍哨"; +wchar_t _PyMa_she [] = L"设社舌蛇舍射涉奢赊赦慑摄"; +wchar_t _PyMa_shen [] = L"什深神申伸身婶肾甚呻绅娠砷沈审渗慎"; +wchar_t _PyMa_sheng [] = L"生升省声胜盛剩牲甥绳圣"; +wchar_t _PyMa_shi [] = L"是十时似事式试实使示始市失释视适驶室师识史诗匙石拾世仕侍虱施狮湿蚀食矢屎士氏势饰恃拭尸柿逝嗜誓噬"; +wchar_t _PyMa_shou [] = L"收手守首寿受兽售授瘦"; +wchar_t _PyMa_shu [] = L"书数熟暑树束输术述抒叔舒枢殊属梳恕竖淑疏蔬孰赎黍署鼠蜀薯曙戍庶墅漱"; +wchar_t _PyMa_shua [] = L"刷耍唰"; +wchar_t _PyMa_shuai [] = L"摔帅率衰甩"; +wchar_t _PyMa_shuan [] = L"拴栓涮"; +wchar_t _PyMa_shuang[] = L"双霜爽孀"; +wchar_t _PyMa_shui [] = L"谁水税睡说"; +wchar_t _PyMa_shun [] = L"吮顺舜瞬"; +wchar_t _PyMa_shuo [] = L"说烁朔硕"; +wchar_t _PyMa_zha [] = L"诈炸榨扎喳渣札眨轧闸铡乍柞"; +wchar_t _PyMa_zhai [] = L"摘宅债寨斋翟窄"; +wchar_t _PyMa_zhan [] = L"展站战沾绽湛粘毡盏斩崭辗占栈詹瞻蘸"; +wchar_t _PyMa_zhang [] = L"长张章彰漳樟涨掌丈仗帐杖胀账障瘴"; +wchar_t _PyMa_zhao [] = L"招昭找沼召兆赵照罩肇爪"; +wchar_t _PyMa_zhe [] = L"这者着浙遮哲折蛰辙锗蔗"; +wchar_t _PyMa_zhen [] = L"真针阵振镇诊侦珍枕帧斟震贞疹砧甄臻"; +wchar_t _PyMa_zheng [] = L"正政整争证郑征挣睁拯蒸怔症狰"; +wchar_t _PyMa_zhi [] = L"之知支只止址至志直值置质智汁芝吱枝织肢脂蜘执侄职植殖旨纸指趾制帜治炙峙挚秩致掷痔窒滞稚"; +wchar_t _PyMa_zhong [] = L"中众重钟忠衷终种肿仲盅"; +wchar_t _PyMa_zhou [] = L"州周皱粥洲昼轴肘帚咒宙诌舟骤"; +wchar_t _PyMa_zhu [] = L"住助⒅熳V髦碇胫裰曛橹鹬钪蛑糁笾鲋踔ぶ镏�"; +wchar_t _PyMa_zhua [] = L"抓"; +wchar_t _PyMa_zhuai [] = L"拽"; +wchar_t _PyMa_zhuan [] = L"专砖转撰篆"; +wchar_t _PyMa_zhuang[] = L"妆庄桩装壮状幢撞"; +wchar_t _PyMa_zhui [] = L"追椎锥坠缀赘"; +wchar_t _PyMa_zhun [] = L"谆准"; +wchar_t _PyMa_zhuo [] = L"捉桌浊卓拙灼茁酌啄琢"; + +u16 _YunMu_none[4] = {0}; +u16 _YunMu_a [4] = {'a'}; +u16 _YunMu_o [4] = {'o'}; +u16 _YunMu_e [4] = {'e'}; +u16 _YunMu_ai [4] = {'a','i'}; +u16 _YunMu_ou [4] = {'o','u'}; +u16 _YunMu_ei [4] = {'e','i'}; +u16 _YunMu_ao [4] = {'a','o'}; +u16 _YunMu_an [4] = {'a','n'}; +u16 _YunMu_en [4] = {'e','n'}; +u16 _YunMu_ang [4] = {'a','n','g'}; +u16 _YunMu_eng [4] = {'e','n','g'}; +u16 _YunMu_ong [4] = {'o','n','g'}; +u16 _YunMu_i [4] = {'i'}; +u16 _YunMu_ia [4] = {'i','a'}; +u16 _YunMu_ie [4] = {'i','e'}; +u16 _YunMu_iao [4] = {'i','a','o'}; +u16 _YunMu_iu [4] = {'i','u'}; +u16 _YunMu_ian [4] = {'i','a','n'}; +u16 _YunMu_in [4] = {'i','n'}; +u16 _YunMu_iang[4] = {'i','a','n','g'}; +u16 _YunMu_ing [4] = {'i','n','g'}; +u16 _YunMu_iong[4] = {'i','o','n','g'}; +u16 _YunMu_u [4] = {'u'}; +u16 _YunMu_ua [4] = {'u','a'}; +u16 _YunMu_ue [4] = {'u','e'}; +u16 _YunMu_uo [4] = {'u','o'}; +u16 _YunMu_uai [4] = {'u','a','i'}; +u16 _YunMu_ui [4] = {'u','i'}; +u16 _YunMu_uan [4] = {'u','a','n'}; +u16 _YunMu_uang[4] = {'u','a','n','g'}; +u16 _YunMu_un [4] = {'u','n'}; +u16 _YunMu_r [4] = {'r'}; +u16 _YunMu_v [4] = {'v'}; +u16 _YunMu_n [4] = {'n'}; +u16 _YunMu_ng [4] = {'n','g'}; +u16 _YunMu_z [4] = {'z'}; + +struct _PyIndexType PyIndex_a[] = { + {_PyMa_a ,_YunMu_none}, + {_PyMa_ai ,_YunMu_i }, + {_PyMa_an ,_YunMu_n }, + {_PyMa_aang ,_YunMu_ang }, + {_PyMa_aao ,_YunMu_ao }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_b[] = { + {_PyMa_b ,_YunMu_none}, + {_PyMa_ba ,_YunMu_a }, + {_PyMa_bai ,_YunMu_ai }, + {_PyMa_ban ,_YunMu_an }, + {_PyMa_bang ,_YunMu_ang }, + {_PyMa_bao ,_YunMu_ao }, + {_PyMa_bei ,_YunMu_ei }, + {_PyMa_ben ,_YunMu_en }, + {_PyMa_beng ,_YunMu_eng }, + {_PyMa_bi ,_YunMu_i }, + {_PyMa_bian ,_YunMu_ian }, + {_PyMa_biao ,_YunMu_iao }, + {_PyMa_bie ,_YunMu_ie }, + {_PyMa_bin ,_YunMu_in }, + {_PyMa_bing ,_YunMu_ing }, + {_PyMa_bo ,_YunMu_o }, + {_PyMa_bu ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_c[] = { + {_PyMa_c ,_YunMu_none}, + {_PyMa_ca ,_YunMu_a }, + {_PyMa_cai ,_YunMu_ai }, + {_PyMa_can ,_YunMu_an }, + {_PyMa_cang ,_YunMu_ang }, + {_PyMa_cao ,_YunMu_ao }, + {_PyMa_ce ,_YunMu_e }, + {_PyMa_ceng ,_YunMu_eng }, + {_PyMa_ci ,_YunMu_i }, + {_PyMa_cong ,_YunMu_ong }, + {_PyMa_cou ,_YunMu_ou }, + {_PyMa_cu ,_YunMu_u }, + {_PyMa_cuan ,_YunMu_uan }, + {_PyMa_cui ,_YunMu_ui }, + {_PyMa_cun ,_YunMu_un }, + {_PyMa_cuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_d[] = { + {_PyMa_d ,_YunMu_none}, + {_PyMa_da ,_YunMu_a }, + {_PyMa_dai ,_YunMu_ai }, + {_PyMa_dan ,_YunMu_an }, + {_PyMa_dang ,_YunMu_ang }, + {_PyMa_dao ,_YunMu_ao }, + {_PyMa_de ,_YunMu_e }, + {_PyMa_deng ,_YunMu_eng }, + {_PyMa_di ,_YunMu_i }, + {_PyMa_dian ,_YunMu_ian }, + {_PyMa_diao ,_YunMu_iao }, + {_PyMa_die ,_YunMu_ie }, + {_PyMa_ding ,_YunMu_ing }, + {_PyMa_diu ,_YunMu_iu }, + {_PyMa_dong ,_YunMu_ong }, + {_PyMa_dou ,_YunMu_ou }, + {_PyMa_du ,_YunMu_u }, + {_PyMa_duan ,_YunMu_uan }, + {_PyMa_dui ,_YunMu_ui }, + {_PyMa_dun ,_YunMu_un }, + {_PyMa_duo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_e[] = { + {_PyMa_e ,_YunMu_none}, + {_PyMa_en ,_YunMu_n }, + {_PyMa_er ,_YunMu_r }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_f[] = { + {_PyMa_f ,_YunMu_none}, + {_PyMa_fa ,_YunMu_a }, + {_PyMa_fan ,_YunMu_an }, + {_PyMa_fang ,_YunMu_ang }, + {_PyMa_fei ,_YunMu_ei }, + {_PyMa_fen ,_YunMu_en }, + {_PyMa_feng ,_YunMu_eng }, + {_PyMa_fo ,_YunMu_o }, + {_PyMa_fou ,_YunMu_ou }, + {_PyMa_fu ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_g[] = { + {_PyMa_g ,_YunMu_none}, + {_PyMa_ga ,_YunMu_a }, + {_PyMa_gai ,_YunMu_ai }, + {_PyMa_gan ,_YunMu_an }, + {_PyMa_gang ,_YunMu_ang }, + {_PyMa_gao ,_YunMu_ao }, + {_PyMa_ge ,_YunMu_e }, + {_PyMa_gei ,_YunMu_ei }, + {_PyMa_gen ,_YunMu_en }, + {_PyMa_geng ,_YunMu_eng }, + {_PyMa_gong ,_YunMu_ong }, + {_PyMa_gou ,_YunMu_ou }, + {_PyMa_gu ,_YunMu_u }, + {_PyMa_gua ,_YunMu_ua }, + {_PyMa_guai ,_YunMu_uai }, + {_PyMa_guan ,_YunMu_uan }, + {_PyMa_guang,_YunMu_uang}, + {_PyMa_gui ,_YunMu_ui }, + {_PyMa_gun ,_YunMu_un }, + {_PyMa_guo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_h[] = { + {_PyMa_h ,_YunMu_none}, + {_PyMa_ha ,_YunMu_a }, + {_PyMa_hai ,_YunMu_ai }, + {_PyMa_han ,_YunMu_an }, + {_PyMa_hang ,_YunMu_ang }, + {_PyMa_hao ,_YunMu_ao }, + {_PyMa_he ,_YunMu_e }, + {_PyMa_hei ,_YunMu_ei }, + {_PyMa_hen ,_YunMu_en }, + {_PyMa_heng ,_YunMu_eng }, + {_PyMa_hong ,_YunMu_ong }, + {_PyMa_hou ,_YunMu_ou }, + {_PyMa_hu ,_YunMu_u }, + {_PyMa_hua ,_YunMu_ua }, + {_PyMa_huai ,_YunMu_uai }, + {_PyMa_huan ,_YunMu_uan }, + {_PyMa_huang,_YunMu_uang}, + {_PyMa_hui ,_YunMu_ui }, + {_PyMa_hun ,_YunMu_un }, + {_PyMa_huo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_j[] = { + {_PyMa_j ,_YunMu_none}, + {_PyMa_ji ,_YunMu_i }, + {_PyMa_jia ,_YunMu_ia }, + {_PyMa_jian ,_YunMu_ian }, + {_PyMa_jiang,_YunMu_iang}, + {_PyMa_jiao ,_YunMu_iao }, + {_PyMa_jie ,_YunMu_ie }, + {_PyMa_jin ,_YunMu_in }, + {_PyMa_jing ,_YunMu_ing }, + {_PyMa_jiong,_YunMu_iong}, + {_PyMa_jiu ,_YunMu_iu }, + {_PyMa_ju ,_YunMu_u }, + {_PyMa_juan ,_YunMu_uan }, + {_PyMa_jue ,_YunMu_ue }, + {_PyMa_jun ,_YunMu_un }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_k[] = { + {_PyMa_k ,_YunMu_none}, + {_PyMa_ka ,_YunMu_a }, + {_PyMa_kai ,_YunMu_ai }, + {_PyMa_kan ,_YunMu_an }, + {_PyMa_kang ,_YunMu_ang }, + {_PyMa_kao ,_YunMu_ao }, + {_PyMa_ke ,_YunMu_e }, + {_PyMa_ken ,_YunMu_en }, + {_PyMa_keng ,_YunMu_eng }, + {_PyMa_kong ,_YunMu_ong }, + {_PyMa_kou ,_YunMu_ou }, + {_PyMa_ku ,_YunMu_u }, + {_PyMa_kua ,_YunMu_ua }, + {_PyMa_kuai ,_YunMu_uai }, + {_PyMa_kuan ,_YunMu_uan }, + {_PyMa_kuang,_YunMu_uang}, + {_PyMa_kui ,_YunMu_ui }, + {_PyMa_kun ,_YunMu_un }, + {_PyMa_kuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_l[] = { + {_PyMa_l ,_YunMu_none}, + {_PyMa_la ,_YunMu_a }, + {_PyMa_lai ,_YunMu_ai }, + {_PyMa_lan ,_YunMu_an }, + {_PyMa_lang ,_YunMu_ang }, + {_PyMa_lao ,_YunMu_ao }, + {_PyMa_le ,_YunMu_e }, + {_PyMa_lei ,_YunMu_ei }, + {_PyMa_leng ,_YunMu_eng }, + {_PyMa_li ,_YunMu_i }, + {_PyMa_lian ,_YunMu_ian }, + {_PyMa_liang,_YunMu_iang}, + {_PyMa_liao ,_YunMu_iao }, + {_PyMa_lie ,_YunMu_ie }, + {_PyMa_lin ,_YunMu_in }, + {_PyMa_ling ,_YunMu_ing }, + {_PyMa_liu ,_YunMu_iu }, + {_PyMa_long ,_YunMu_ong }, + {_PyMa_lou ,_YunMu_ou }, + {_PyMa_lu ,_YunMu_u }, + {_PyMa_luan ,_YunMu_uan }, + {_PyMa_lue ,_YunMu_ue }, + {_PyMa_lun ,_YunMu_un }, + {_PyMa_luo ,_YunMu_uo }, + {_PyMa_lv ,_YunMu_v }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_m[] = { + {_PyMa_m ,_YunMu_none}, + {_PyMa_ma ,_YunMu_a }, + {_PyMa_mai ,_YunMu_ai }, + {_PyMa_man ,_YunMu_an }, + {_PyMa_mang ,_YunMu_ang }, + {_PyMa_mao ,_YunMu_ao }, + {_PyMa_me ,_YunMu_e }, + {_PyMa_mei ,_YunMu_ei }, + {_PyMa_men ,_YunMu_en }, + {_PyMa_meng ,_YunMu_eng }, + {_PyMa_mi ,_YunMu_i }, + {_PyMa_mian ,_YunMu_ian }, + {_PyMa_miao ,_YunMu_iao }, + {_PyMa_mie ,_YunMu_ie }, + {_PyMa_min ,_YunMu_in }, + {_PyMa_ming ,_YunMu_ing }, + {_PyMa_miu ,_YunMu_iu }, + {_PyMa_mo ,_YunMu_o }, + {_PyMa_mou ,_YunMu_ou }, + {_PyMa_mu ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_n[] = { + {_PyMa_n ,_YunMu_none}, + {_PyMa_na ,_YunMu_a }, + {_PyMa_nai ,_YunMu_ai }, + {_PyMa_nan ,_YunMu_an }, + {_PyMa_nang ,_YunMu_ang }, + {_PyMa_nao ,_YunMu_ao }, + {_PyMa_ne ,_YunMu_e }, + {_PyMa_nei ,_YunMu_ei }, + {_PyMa_nen ,_YunMu_en }, + {_PyMa_neng ,_YunMu_eng }, + {_PyMa_ni ,_YunMu_i }, + {_PyMa_nian ,_YunMu_ian }, + {_PyMa_niang,_YunMu_iang}, + {_PyMa_niao ,_YunMu_iao }, + {_PyMa_nie ,_YunMu_ie }, + {_PyMa_nin ,_YunMu_in }, + {_PyMa_ning ,_YunMu_ing }, + {_PyMa_niu ,_YunMu_iu }, + {_PyMa_nong ,_YunMu_ong }, + {_PyMa_nu ,_YunMu_u }, + {_PyMa_nuan ,_YunMu_uan }, + {_PyMa_nue ,_YunMu_ue }, + {_PyMa_nuo ,_YunMu_uo }, + {_PyMa_nv ,_YunMu_v }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_o[] = { + {_PyMa_o ,_YunMu_none}, + {_PyMa_ou ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_p[] = { + {_PyMa_p ,_YunMu_none}, + {_PyMa_pa ,_YunMu_a }, + {_PyMa_pai ,_YunMu_ai }, + {_PyMa_pan ,_YunMu_an }, + {_PyMa_pang ,_YunMu_ang }, + {_PyMa_pao ,_YunMu_ao }, + {_PyMa_pei ,_YunMu_ei }, + {_PyMa_pen ,_YunMu_en }, + {_PyMa_peng ,_YunMu_eng }, + {_PyMa_pi ,_YunMu_i }, + {_PyMa_pian ,_YunMu_ian }, + {_PyMa_piao ,_YunMu_iao }, + {_PyMa_pie ,_YunMu_ie }, + {_PyMa_pin ,_YunMu_in }, + {_PyMa_ping ,_YunMu_ing }, + {_PyMa_po ,_YunMu_o }, + {_PyMa_pou ,_YunMu_ou }, + {_PyMa_pu ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_q[] = { + {_PyMa_q ,_YunMu_none}, + {_PyMa_qi ,_YunMu_i }, + {_PyMa_qia ,_YunMu_ia }, + {_PyMa_qian ,_YunMu_ian }, + {_PyMa_qiang,_YunMu_iang}, + {_PyMa_qiao ,_YunMu_iao }, + {_PyMa_qie ,_YunMu_ie }, + {_PyMa_qin ,_YunMu_in }, + {_PyMa_qing ,_YunMu_ing }, + {_PyMa_qiong,_YunMu_iong}, + {_PyMa_qiu ,_YunMu_iu }, + {_PyMa_qu ,_YunMu_u }, + {_PyMa_quan ,_YunMu_uan }, + {_PyMa_que ,_YunMu_ue }, + {_PyMa_qun ,_YunMu_un }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_r[] = { + {_PyMa_r ,_YunMu_none}, + {_PyMa_ran ,_YunMu_an }, + {_PyMa_rang ,_YunMu_ang }, + {_PyMa_rao ,_YunMu_ao }, + {_PyMa_re ,_YunMu_e }, + {_PyMa_ren ,_YunMu_en }, + {_PyMa_reng ,_YunMu_eng }, + {_PyMa_ri ,_YunMu_i }, + {_PyMa_rong ,_YunMu_ong }, + {_PyMa_rou ,_YunMu_ou }, + {_PyMa_ru ,_YunMu_u }, + {_PyMa_ruan ,_YunMu_uan }, + {_PyMa_rui ,_YunMu_ui }, + {_PyMa_run ,_YunMu_un }, + {_PyMa_ruo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_s[] = { + {_PyMa_s ,_YunMu_none}, + {_PyMa_sa ,_YunMu_a }, + {_PyMa_sai ,_YunMu_ai }, + {_PyMa_san ,_YunMu_an }, + {_PyMa_sang ,_YunMu_ang }, + {_PyMa_sao ,_YunMu_ao }, + {_PyMa_se ,_YunMu_e }, + {_PyMa_sen ,_YunMu_en }, + {_PyMa_seng ,_YunMu_eng }, + {_PyMa_si ,_YunMu_i }, + {_PyMa_song ,_YunMu_ong }, + {_PyMa_sou ,_YunMu_ou }, + {_PyMa_su ,_YunMu_u }, + {_PyMa_suan ,_YunMu_uan }, + {_PyMa_sui ,_YunMu_ui }, + {_PyMa_sun ,_YunMu_un }, + {_PyMa_suo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_t[] = { + {_PyMa_t ,_YunMu_none}, + {_PyMa_ta ,_YunMu_a }, + {_PyMa_tai ,_YunMu_ai }, + {_PyMa_tan ,_YunMu_an }, + {_PyMa_tang ,_YunMu_ang }, + {_PyMa_tao ,_YunMu_ao }, + {_PyMa_te ,_YunMu_e }, + {_PyMa_teng ,_YunMu_eng }, + {_PyMa_ti ,_YunMu_i }, + {_PyMa_tian ,_YunMu_ian }, + {_PyMa_tiao ,_YunMu_iao }, + {_PyMa_tie ,_YunMu_ie }, + {_PyMa_ting ,_YunMu_ing }, + {_PyMa_tong ,_YunMu_ong }, + {_PyMa_tou ,_YunMu_ou }, + {_PyMa_tu ,_YunMu_u }, + {_PyMa_tuan ,_YunMu_uan }, + {_PyMa_tui ,_YunMu_ui }, + {_PyMa_tun ,_YunMu_un }, + {_PyMa_tuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_w[] = { + {_PyMa_w ,_YunMu_none}, + {_PyMa_wa ,_YunMu_a }, + {_PyMa_wai ,_YunMu_ai }, + {_PyMa_wan ,_YunMu_an }, + {_PyMa_wang ,_YunMu_ang }, + {_PyMa_wei ,_YunMu_ei }, + {_PyMa_wen ,_YunMu_en }, + {_PyMa_weng ,_YunMu_eng }, + {_PyMa_wo ,_YunMu_o }, + {_PyMa_wu ,_YunMu_u }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_x[] = { + {_PyMa_x ,_YunMu_none}, + {_PyMa_xi ,_YunMu_i }, + {_PyMa_xia ,_YunMu_ia }, + {_PyMa_xian ,_YunMu_ian }, + {_PyMa_xiang,_YunMu_iang}, + {_PyMa_xiao ,_YunMu_iao }, + {_PyMa_xie ,_YunMu_ie }, + {_PyMa_xin ,_YunMu_in }, + {_PyMa_xing ,_YunMu_ing }, + {_PyMa_xiong,_YunMu_iong}, + {_PyMa_xiu ,_YunMu_iu }, + {_PyMa_xu ,_YunMu_u }, + {_PyMa_xuan ,_YunMu_uan }, + {_PyMa_xue ,_YunMu_ue }, + {_PyMa_xun ,_YunMu_un }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_y[] = { + {_PyMa_y ,_YunMu_none}, + {_PyMa_ya ,_YunMu_a }, + {_PyMa_yan ,_YunMu_an }, + {_PyMa_yang ,_YunMu_ang }, + {_PyMa_yao ,_YunMu_ao }, + {_PyMa_ye ,_YunMu_e }, + {_PyMa_yi ,_YunMu_i }, + {_PyMa_yin ,_YunMu_in }, + {_PyMa_ying ,_YunMu_ing }, + {_PyMa_yo ,_YunMu_o }, + {_PyMa_yong ,_YunMu_ong }, + {_PyMa_you ,_YunMu_ou }, + {_PyMa_yu ,_YunMu_u }, + {_PyMa_yuan ,_YunMu_uan }, + {_PyMa_yue ,_YunMu_ue }, + {_PyMa_yun ,_YunMu_un }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_z[] = { + {_PyMa_z ,_YunMu_none}, + {_PyMa_za ,_YunMu_a }, + {_PyMa_zai ,_YunMu_ai }, + {_PyMa_zan ,_YunMu_an }, + {_PyMa_zang ,_YunMu_ang }, + {_PyMa_zao ,_YunMu_ao }, + {_PyMa_ze ,_YunMu_e }, + {_PyMa_zei ,_YunMu_ei }, + {_PyMa_zen ,_YunMu_en }, + {_PyMa_zeng ,_YunMu_eng }, + {_PyMa_zi ,_YunMu_i }, + {_PyMa_zong ,_YunMu_ong }, + {_PyMa_zou ,_YunMu_ou }, + {_PyMa_zu ,_YunMu_u }, + {_PyMa_zuan ,_YunMu_uan }, + {_PyMa_zui ,_YunMu_ui }, + {_PyMa_zun ,_YunMu_un }, + {_PyMa_zuo ,_YunMu_uo }, + {_PyMa_zz ,_YunMu_z }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_ch[] = { + {_PyMa_cha ,_YunMu_a }, + {_PyMa_chai ,_YunMu_ai }, + {_PyMa_chan ,_YunMu_an }, + {_PyMa_chang ,_YunMu_ang }, + {_PyMa_chao ,_YunMu_ao }, + {_PyMa_che ,_YunMu_e }, + {_PyMa_chen ,_YunMu_en }, + {_PyMa_cheng ,_YunMu_eng }, + {_PyMa_chi ,_YunMu_i }, + {_PyMa_chong ,_YunMu_ong }, + {_PyMa_chou ,_YunMu_ou }, + {_PyMa_chu ,_YunMu_u }, + {_PyMa_chuai ,_YunMu_uai }, + {_PyMa_chuan ,_YunMu_uan }, + {_PyMa_chuang,_YunMu_uang}, + {_PyMa_chui ,_YunMu_ui }, + {_PyMa_chun ,_YunMu_un }, + {_PyMa_chuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_sh[] = { + {_PyMa_sha ,_YunMu_a }, + {_PyMa_shai ,_YunMu_ai }, + {_PyMa_shan ,_YunMu_an }, + {_PyMa_shang ,_YunMu_ang }, + {_PyMa_shao ,_YunMu_ao }, + {_PyMa_she ,_YunMu_e }, + {_PyMa_shen ,_YunMu_en }, + {_PyMa_sheng ,_YunMu_eng }, + {_PyMa_shi ,_YunMu_i }, + {_PyMa_shou ,_YunMu_ou }, + {_PyMa_shu ,_YunMu_u }, + {_PyMa_shua ,_YunMu_ua }, + {_PyMa_shuai ,_YunMu_uai }, + {_PyMa_shuan ,_YunMu_uan }, + {_PyMa_shuang,_YunMu_uang}, + {_PyMa_shui ,_YunMu_ui }, + {_PyMa_shun ,_YunMu_un }, + {_PyMa_shuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType PyIndex_zh[] = { + {_PyMa_zha ,_YunMu_a }, + {_PyMa_zhai ,_YunMu_ai }, + {_PyMa_zhan ,_YunMu_an }, + {_PyMa_zhang ,_YunMu_ang }, + {_PyMa_zhao ,_YunMu_ao }, + {_PyMa_zhe ,_YunMu_e }, + {_PyMa_zhen ,_YunMu_en }, + {_PyMa_zheng ,_YunMu_eng }, + {_PyMa_zhi ,_YunMu_i }, + {_PyMa_zhong ,_YunMu_ong }, + {_PyMa_zhou ,_YunMu_ou }, + {_PyMa_zhu ,_YunMu_u }, + {_PyMa_zhua ,_YunMu_ua }, + {_PyMa_zhuai ,_YunMu_uai }, + {_PyMa_zhuan ,_YunMu_uan }, + {_PyMa_zhuang,_YunMu_uang}, + {_PyMa_zhui ,_YunMu_ui }, + {_PyMa_zhun ,_YunMu_un }, + {_PyMa_zhuo ,_YunMu_uo }, + {NULL ,NULL} +}; + +struct _PyIndexType *PyIndexPointer[] = { + PyIndex_a, + PyIndex_b, + PyIndex_c, + PyIndex_d, + PyIndex_e, + PyIndex_f, + PyIndex_g, + PyIndex_h, + NULL, + PyIndex_j, + PyIndex_k, + PyIndex_l, + PyIndex_m, + PyIndex_n, + PyIndex_o, + PyIndex_p, + PyIndex_q, + PyIndex_r, + PyIndex_s, + PyIndex_t, + NULL, + NULL, + PyIndex_w, + PyIndex_x, + PyIndex_y, + PyIndex_z, +}; + +wchar_t *decode_syllables(const u16 *syllables) +{ + struct _PyIndexType *p1 = NULL; + const u16 *p2 = syllables; + s32 s = 0; + + if (syllables == NULL) { + return NULL; + } + + if (p2[1] == 'h') { + if (p2[0] == 'z') { + p1 = PyIndex_zh; + } + else if (p2[0] == 'c') { + p1 = PyIndex_ch; + } + else if (p2[0] == 's') { + p1 = PyIndex_sh; + } + p2 += 2; + s = 3 * sizeof(u16); + } + else { + p1 = PyIndexPointer[p2[0] - 'a']; + p2++; + s = 4 * sizeof(u16); + } + + if (p1 == NULL) { + return NULL; + } + + while (p1->syllables && p1->final) { + if (memcmp(p1->final, p2, s) == 0) { + return p1->syllables; + } + p1++; + } + + return NULL; +} diff --git a/src/raw_i2c.cpp b/src/raw_i2c.cpp new file mode 100644 index 0000000..20522f9 --- /dev/null +++ b/src/raw_i2c.cpp @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sgi_types.h" + +#define CMD_UNLOCK 0xC0 +#define CMD_LOCK 0xC1 +#define CMD_STATE 0xC2 +#define CMD_CANCEL 0xC3 + +static int i2c_comm_send(u8 addr, u8 *buf, int len) +{ + int fd = -1; + int r = 0; + struct i2c_msg msg[1]; + struct i2c_rdwr_ioctl_data e2prom_data; + + /* 打开I2C设备 */ + fd = open("/dev/i2c/0", O_RDWR); + if (fd < 0) { + printf("open i2c device fail.\n"); + goto err; + } + + /* 设定超时时间,以10ms为单位 */ + ioctl(fd, I2C_TIMEOUT, 1); + + /* 设定重复次数 */ + ioctl(fd, I2C_RETRIES, 2); + + /* 准备写入数据 */ + e2prom_data.nmsgs = 1; + e2prom_data.msgs = msg; + e2prom_data.msgs[0].buf = buf; + e2prom_data.msgs[0].len = len; + e2prom_data.msgs[0].flags = 0; /* 写入 */ + e2prom_data.msgs[0].addr = addr; + + /* 执行I2C总线操作 */ + r = ioctl(fd, I2C_RDWR, (unsigned long)&e2prom_data); + if (r < 0) { + //printf("send ioctl to i2c device fail.\n"); + goto err; + } + + /* 操作成功,返回实际数据长度 */ + r = 0; + +err: + if (fd != -1) { + close(fd); + } + + return r; +} + +static int i2c_comm_recv(u8 addr, u8 *buf, int len) +{ + int fd = -1; + int r = 0; + struct i2c_msg msg[1]; + struct i2c_rdwr_ioctl_data e2prom_data; + + /* 打开I2C设备 */ + fd = open("/dev/i2c/0", O_RDWR); + if (fd < 0) { + printf("open i2c device fail.\n"); + goto err; + } + + /* 设定超时时间,以10ms为单位 */ + ioctl(fd, I2C_TIMEOUT, 1); + + /* 设定重复次数 */ + ioctl(fd, I2C_RETRIES, 2); + + /* 准备写入数据 */ + e2prom_data.nmsgs = 1; + e2prom_data.msgs = msg; + e2prom_data.msgs[0].buf = buf; + e2prom_data.msgs[0].len = len; + e2prom_data.msgs[0].flags = I2C_M_RD; /* 读取 */ + e2prom_data.msgs[0].addr = addr; + + /* 执行I2C总线操作 */ + r = ioctl(fd, I2C_RDWR, (unsigned long)&e2prom_data); + if (r < 0) { + //printf("send ioctl to i2c device fail.\n"); + goto err; + } + + /* 操作成功,返回实际数据长度 */ + r = 0; + +err: + if (fd != -1) { + close(fd); + } + + return r; +} + +static u8 calc_cks(u8 *data, int len) +{ + u8 t = 0; + + while (len-- > 0) { + t += *data++; + } + + return t; +} + +s32 i2c_comm_unlock(u8 addr) +{ + u8 buf[8] = {0}; + + printf("i2c comm, addr: %d\n", addr); + buf[0] = 0x5A; + buf[1] = 0xA5; + buf[2] = CMD_UNLOCK; + buf[7] = calc_cks(buf, 7); + if (i2c_comm_send(addr, buf, sizeof(buf)) != 0) { + printf("i2c comm unlock fail.\n"); + return -1; + } + printf("i2c comm unlock ok.\n"); + + return 0; +} + +s32 i2c_comm_lock(u8 addr) +{ + u8 buf[8] = {0}; + + buf[0] = 0x5A; + buf[1] = 0xA5; + buf[2] = CMD_LOCK; + buf[7] = calc_cks(buf, 7); + if (i2c_comm_send(addr, buf, sizeof(buf)) != 0) { + printf("i2c comm unlock fail.\n"); + return -1; + } + //printf("i2c comm unlock ok.\n"); + + return 0; +} + +s32 i2c_comm_cancel_alarm(u8 addr) +{ + u8 buf[8] = {0}; + + printf("i2c comm, addr: %d\n", addr); + buf[0] = 0x5A; + buf[1] = 0xA5; + buf[2] = CMD_CANCEL; + buf[7] = calc_cks(buf, 7); + if (i2c_comm_send(addr, buf, sizeof(buf)) != 0) { + printf("i2c comm cancel alarm fail.\n"); + return -1; + } + printf("i2c comm cancel alarm ok.\n"); + + return 0; +} + +s32 i2c_comm_update_state(u8 addr) +{ + u8 buf[8] = {0}; + + printf("i2c comm, addr: %d\n", addr); + buf[0] = 0x5A; + buf[1] = 0xA5; + buf[2] = CMD_STATE; + buf[7] = calc_cks(buf, 7); + if (i2c_comm_send(addr, buf, sizeof(buf)) != 0) { + printf("i2c comm update state fail.\n"); + return -1; + } + //printf("i2c comm update state ok.\n"); + + return 0; +} + +s32 i2c_comm_read_state(u8 addr, u8 *state) +{ + u8 buf[8] = {0}; + + if (i2c_comm_recv(addr, buf, sizeof(buf)) != 0) { + //printf("i2c comm read state fail.\n"); + return -1; + } + + /* */ + if (buf[0] != 0x66 || buf[1] != 0x99) { + printf("i2c comm read head error.\n"); + return -1; + } + + if (buf[7] != calc_cks(buf, 7)) { + printf("i2c comm read cks error.\n"); + return -1; + } + + memcpy(state, &buf[3], 4); + + return 0; +} \ No newline at end of file diff --git a/src/sgi_base.cpp b/src/sgi_base.cpp new file mode 100755 index 0000000..d90e020 --- /dev/null +++ b/src/sgi_base.cpp @@ -0,0 +1,1052 @@ +#include "global_func.h" + +/* global variable define */ +static u32 kernel_handle_id = 1024; +struct passport_data g_passport; +struct alarm_data g_alarm_data; + +static s32 s_mfcard_fd = -1; + +const u8 g_box_addr[BOX_NUMS] = { + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69, + 0x6a,0x6b, +}; + +u32 request_handle(void) +{ + return kernel_handle_id++; +} + +SDL_Surface *clone_surface(SDL_Surface *image) +{ + SDL_Surface *surface; + Uint32 rmask, gmask, bmask, amask; + + assert(image); + + rmask = image->format->Rmask; + gmask = image->format->Gmask; + bmask = image->format->Bmask; + amask = image->format->Amask; + + surface = SDL_CreateRGBSurface(SDL_SWSURFACE, image->w, image->h, 32, + rmask, gmask, bmask, amask); + if (surface) { + SDL_BlitSurface(image, NULL, surface, NULL); + return surface; + } + + return NULL; +} + +void release_clone_surface(SDL_Surface *image) +{ + if (image) { + SDL_FreeSurface(image); + } +} + +void sgi_edit_insert_text(struct sgi_edit *object, u16 text) +{ + u32 r; + + r = sgi_len16(object->text); + + if (text == DEL_CHAR) { + object->text[r - 1] = 0; + } + else { + if (object->mask == MSK_DIGIT) { + if (!iswdigit(text)) { + return; + } + } + + if (r >= object->word_max) { + return; + } + + if (r < sizeof(object->text) / sizeof(u16) - 2) { + object->text[r] = text; + object->text[r + 1] = 0; + } + } +} + + +void set_object_default_func(struct sgi_form *form) +{ + if (!form->init) { + form->init = sgi_form_init_default; + } + if (!form->deinit) { + form->deinit = sgi_form_deinit_default; + } + if (!form->frame) { + form->frame = sgi_form_frame_default; + } + if (!form->render) { + form->render = sgi_form_render_default; + } +} + +void set_object_default_func(union sgi_object *object) +{ + switch (object->type) { + case SGI_WINDOW: + if (!object->window.init) { + object->window.init = sgi_window_init_default; + } + if (!object->window.deinit) { + object->window.deinit = sgi_window_deinit_default; + } + if (!object->window.frame) { + object->window.frame = sgi_window_frame_default; + } + if (!object->window.render) { + object->window.render = sgi_window_render_default; + } + break; + + case SGI_PICTURE: + if (!object->picture.init) { + object->picture.init = sgi_picture_init_default; + } + if (!object->picture.deinit) { + object->picture.deinit = sgi_picture_deinit_default; + } + if (!object->picture.frame) { + object->picture.frame = sgi_picture_frame_default; + } + if (!object->picture.render) { + object->picture.render = sgi_picture_render_default; + } + break; + + case SGI_LABEL: + if (!object->label.init) { + object->label.init = sgi_label_init_default; + } + if (!object->label.deinit) { + object->label.deinit = sgi_label_deinit_default; + } + if (!object->label.frame) { + object->label.frame = sgi_label_frame_default; + } + if (!object->label.render) { + object->label.render = sgi_label_render_default; + } + break; + + case SGI_EDIT: + if (!object->edit.init) { + object->edit.init = sgi_edit_init_default; + } + if (!object->edit.deinit) { + object->edit.deinit = sgi_edit_deinit_default; + } + if (!object->edit.frame) { + object->edit.frame = sgi_edit_frame_default; + } + if (!object->edit.render) { + object->edit.render = sgi_edit_render_default; + } + break; + + case SGI_BUTTON: + if (!object->button.init) { + object->button.init = sgi_button_init_default; + } + if (!object->button.deinit) { + object->button.deinit = sgi_button_deinit_default; + } + if (!object->button.frame) { + object->button.frame = sgi_button_frame_default; + } + if (!object->button.render) { + object->button.render = sgi_button_render_default; + } + if (!object->button.down) { + object->button.down = sgi_button_down_default; + } + if (!object->button.up) { + object->button.up = sgi_button_up_default; + } + if (!object->button.click) { + object->button.click = sgi_button_click_default; + } + break; + + case SGI_IME: + if (!object->ime.init) { + object->ime.init = sgi_ime_init_default; + } + if (!object->ime.deinit) { + object->ime.deinit = sgi_ime_deinit_default; + } + if (!object->ime.frame) { + object->ime.frame = sgi_ime_frame_default; + } + if (!object->ime.render) { + object->ime.render = sgi_ime_render_default; + } +// if (!object->ime.down) { +// object->ime.down = sgi_ime_down_default; +// } +// if (!object->ime.up) { +// object->ime.up = sgi_ime_up_default; +// } + break; + + case SGI_BOX: + if (!object->box.init) { + object->box.init = sgi_box_init_default; + } + if (!object->box.deinit) { + object->box.deinit = sgi_box_deinit_default; + } + if (!object->box.frame) { + object->box.frame = sgi_box_frame_default; + } + if (!object->box.render) { + object->box.render = sgi_box_render_default; + } + if (!object->box.down) { + object->box.down = sgi_box_down_default; + } + if (!object->box.up) { + object->box.up = sgi_box_up_default; + } + break; + + case SGI_GRID: + if (!object->grid.init) { + object->grid.init = sgi_grid_init_default; + } + if (!object->grid.deinit) { + object->grid.deinit = sgi_grid_deinit_default; + } + if (!object->grid.frame) { + object->grid.frame = sgi_grid_frame_default; + } + if (!object->grid.render) { + object->grid.render = sgi_grid_render_default; + } + break; + + case SGI_PHOTO: + if (!object->photo.render) { + object->photo.render = sgi_photo_render_default; + } + break; + + case SGI_MSGBOX: + if (!object->msgbox.init) { + object->msgbox.init = sgi_msgbox_init_default; + } + if (!object->msgbox.deinit) { + object->msgbox.deinit = sgi_msgbox_deinit_default; + } + if (!object->msgbox.frame) { + object->msgbox.frame = sgi_msgbox_frame_default; + } + if (!object->msgbox.render) { + object->msgbox.render = sgi_msgbox_render_default; + } + break; + + case SGI_RADIO: + if (!object->radio.init) { + object->radio.init = sgi_radio_init_default; + } + if (!object->radio.deinit) { + object->radio.deinit = sgi_radio_deinit_default; + } + if (!object->radio.frame) { + object->radio.frame = sgi_radio_frame_default; + } + if (!object->radio.render) { + object->radio.render = sgi_radio_render_default; + } + break; + + case SGI_CHECK: + if (!object->check.init) { + object->check.init = sgi_check_init_default; + } + if (!object->check.deinit) { + object->check.deinit = sgi_check_deinit_default; + } + if (!object->check.frame) { + object->check.frame = sgi_check_frame_default; + } + if (!object->check.render) { + object->check.render = sgi_check_render_default; + } + break; + + case SGI_UPDOWN: + if (!object->updown.init) { + object->updown.init = sgi_updown_init_default; + } + if (!object->updown.deinit) { + object->updown.deinit = sgi_updown_deinit_default; + } + if (!object->updown.frame) { + object->updown.frame = sgi_updown_frame_default; + } + if (!object->updown.render) { + object->updown.render = sgi_updown_render_default; + } + break; + + case SGI_INDICATOR: + if (!object->indicator.init) { + object->indicator.init = sgi_indicator_init_default; + } + if (!object->indicator.deinit) { + object->indicator.deinit = sgi_indicator_deinit_default; + } + if (!object->indicator.frame) { + object->indicator.frame = sgi_indicator_frame_default; + } + if (!object->indicator.render) { + object->indicator.render = sgi_indicator_render_default; + } + break; + + default: + break; + } +} + +void invalidate_rect(struct sgi_form *form, s16 x1, s16 y1, s16 x2, s16 y2) +{ + form->dirty = 1; + + if (form->x1 > x1) { + form->x1 = x1; + } + + if (form->y1 > y1) { + form->y1 = y1; + } + + if (form->x2 < x2) { + form->x2 = x2; + } + + if (form->y2 < y2) { + form->y2 = y2; + } +} + +void set_object_pos(union sgi_object *object, s16 x, s16 y, s16 w, s16 h, s16 z) +{ + switch (object->type) { + case SGI_WINDOW: + object->window.x = x; + object->window.y = y; + object->window.w = w; + object->window.h = h; + object->window.z = z; + break; + + case SGI_PICTURE: + object->picture.x = x; + object->picture.y = y; + object->picture.w = w; + object->picture.h = h; + object->picture.z = z; + break; + + case SGI_LABEL: + object->label.x = x; + object->label.y = y; + object->label.w = w; + object->label.h = h; + object->label.z = z; + break; + + case SGI_EDIT: + object->edit.x = x; + object->edit.y = y; + object->edit.w = w; + object->edit.h = h; + object->edit.z = z; + break; + + case SGI_BUTTON: + object->button.x = x; + object->button.y = y; + object->button.w = w; + object->button.h = h; + object->button.z = z; + break; + + case SGI_IME: + object->ime.x = x; + object->ime.y = y; + object->ime.w = w; + object->ime.h = h; + object->ime.z = z; + break; + + case SGI_BOX: + object->box.x = x; + object->box.y = y; + object->box.w = w; + object->box.h = h; + object->box.z = z; + break; + + case SGI_GRID: + object->grid.x = x; + object->grid.y = y; + object->grid.w = w; + object->grid.h = h; + object->grid.z = z; + break; + + case SGI_PHOTO: + object->photo.x = x; + object->photo.y = y; + object->photo.w = w; + object->photo.h = h; + object->photo.z = z; + break; + + case SGI_RADIO: + object->radio.x = x; + object->radio.y = y; + object->radio.w = w; + object->radio.h = h; + object->radio.z = z; + break; + + case SGI_CHECK: + object->check.x = x; + object->check.y = y; + object->check.w = w; + object->check.h = h; + object->check.z = z; + break; + + case SGI_UPDOWN: + object->updown.x = x; + object->updown.y = y; + object->updown.w = w; + object->updown.h = h; + object->updown.z = z; + break; + + case SGI_INDICATOR: + object->indicator.x = x; + object->indicator.y = y; + object->indicator.w = w; + object->indicator.h = h; + object->indicator.z = z; + break; + + default: + break; + } +} + +void set_object_text_u(struct sgi_label *object, u16 *text) +{ + if (text == NULL) { + memset(object->caption, 0, sizeof(object->caption)); + } + else { + sgi_ncp16(object->caption, text, COUNTOF(object->caption)); + } +} + +void set_object_text_u(struct sgi_edit *object, u16 *text) +{ + if (text == NULL) { + memset(object->text, 0, sizeof(object->text)); + } + else { + sgi_ncp16(object->text, text, COUNTOF(object->text)); + } +} + +void set_object_text_w(struct sgi_label *object, w32 *text) +{ + if (text == NULL) { + memset(object->caption, 0, sizeof(object->caption)); + } + else { + sgi_ncpw2u(object->caption, text, COUNTOF(object->caption)); + } +} + +void set_object_text_w(struct sgi_edit *object, w32 *text) +{ + if (text == NULL) { + memset(object->text, 0, sizeof(object->text)); + } + else { + sgi_ncpw2u(object->text, text, COUNTOF(object->text)); + } +} + +void get_object_text_u(struct sgi_label *object, u16 *text) +{ + sgi_ncp16(text, object->caption, COUNTOF(object->caption)); +} + +void get_object_text_u(struct sgi_edit *object, u16 *text) +{ + sgi_ncp16(text, object->text, COUNTOF(object->text)); +} + +void set_object_focus(union sgi_object *object) +{ + if (object->type == SGI_EDIT) { + object->edit.parent->focus_handle = object->edit.handle; + } +} + +void set_object_parent(union sgi_object *object, struct sgi_form *form) +{ + switch (object->type) { + case SGI_WINDOW: + object->window.parent = form; + break; + + case SGI_PICTURE: + object->picture.parent = form; + break; + + case SGI_LABEL: + object->label.parent = form; + break; + + case SGI_EDIT: + object->edit.parent = form; + break; + + case SGI_BUTTON: + object->button.parent = form; + break; + + case SGI_IME: + object->ime.parent = form; + break; + + case SGI_BOX: + object->box.parent = form; + break; + + case SGI_GRID: + object->grid.parent = form; + break; + + case SGI_PHOTO: + object->photo.parent = form; + break; + + case SGI_MSGBOX: + object->msgbox.parent = form; + break; + + case SGI_RADIO: + object->radio.parent = form; + break; + + case SGI_CHECK: + object->check.parent = form; + break; + + case SGI_UPDOWN: + object->updown.parent = form; + break; + + case SGI_INDICATOR: + object->indicator.parent = form; + break; + + default: + break; + } +} + +void set_object_image(union sgi_object *object, char *image1, char *image2, + char *image3, char *image4, u32 flags) +{ + switch (object->type) { + case SGI_WINDOW: + object->window.image.name = image1; + object->window.image.flags = flags; + break; + + case SGI_PICTURE: + object->picture.image.name = image1; + object->picture.image.flags = flags; + break; + + case SGI_LABEL: + break; + + case SGI_EDIT: + object->edit.image.name = image1; + object->edit.image.flags = flags; + break; + + case SGI_BUTTON: + object->button.back[0].name = image1; + object->button.back[1].name = image2; + object->button.back[2].name = image3; + object->button.front.name = image4; + object->button.back[0].flags = flags; + object->button.back[1].flags = flags; + object->button.back[2].flags = flags; + object->button.front.flags = flags; + break; + + case SGI_IME: + object->ime.back[0].name = image1; + object->ime.back[1].name = image2; + object->ime.back[0].flags = flags; + object->ime.back[1].flags = flags; + break; + + case SGI_BOX: + object->box.back[0].name = image1; + object->box.back[1].name = image2; + object->box.back[2].name = image3; + object->box.back[3].name = image4; + object->box.back[0].flags = flags; + object->box.back[1].flags = flags; + object->box.back[2].flags = flags; + object->box.back[3].flags = flags; + break; + + case SGI_GRID: + object->grid.back.name = image1; + object->grid.action.name = image2; + object->grid.back.flags = flags; + object->grid.action.flags = flags; + break; + + case SGI_MSGBOX: + object->msgbox.image[0].name = image1; + object->msgbox.image[1].name = image2; + object->msgbox.image[2].name = image3; + object->msgbox.image[3].name = image4; + object->msgbox.image[0].flags = flags; + object->msgbox.image[1].flags = flags; + object->msgbox.image[2].flags = flags; + object->msgbox.image[3].flags = flags; + break; + + case SGI_RADIO: + object->radio.image[0].name = image1; + object->radio.image[1].name = image2; + object->radio.image[0].flags = flags; + object->radio.image[1].flags = flags; + break; + + case SGI_CHECK: + object->check.image[0].name = image1; + object->check.image[1].name = image2; + object->check.image[0].flags = flags; + object->check.image[1].flags = flags; + break; + + case SGI_UPDOWN: + object->updown.image[0].name = image1; + object->updown.image[1].name = image2; + object->updown.image[0].flags = flags; + object->updown.image[1].flags = flags; + break; + + case SGI_INDICATOR: + object->indicator.image[0].name = image1; + object->indicator.image[1].name = image2; + object->indicator.image[0].flags = flags; + object->indicator.image[1].flags = flags; + break; + + default: + break; + } +} + +void set_object_font(union sgi_object *object, char *name, u32 size, SDL_Color color) +{ + switch (object->type) { + case SGI_WINDOW: + break; + + case SGI_LABEL: + object->label.font.name = name; + object->label.font.size = size; + object->label.fcolor = color; + break; + + case SGI_EDIT: + object->edit.font.name = name; + object->edit.font.size = size; + object->edit.fcolor = color; + break; + + case SGI_BUTTON: + break; + + case SGI_IME: + object->ime.font.name = name; + object->ime.font.size = size; + break; + + case SGI_BOX: + object->box.font.name = name; + object->box.font.size = size; + break; + + case SGI_GRID: + object->grid.font.name = name; + object->grid.font.size = size; + break; + + case SGI_MSGBOX: + object->msgbox.font.name = name; + object->msgbox.font.size = size; + break; + + case SGI_UPDOWN: + object->updown.font.name = name; + object->updown.font.size = size; + object->updown.fcolor = color; + break; + + case SGI_INDICATOR: + break; + + default: + break; + } +} + +void register_window(struct sgi_form *form, struct sgi_window *wnd) +{ + assert(form != NULL && wnd != NULL); + form->wnd = wnd; +} + +void register_ime(struct sgi_form *form) +{ + s32 r = 0; + assert(form != NULL); + + sgi_ime_create(); + + if (!g_sgi_ime.initialized) { + r = g_sgi_ime.init(&g_sgi_ime); + printf("init ime module: %d\n", r); + } + + if (r == 0) { + form->ime = &g_sgi_ime; + g_sgi_ime.parent = form; + printf("register ime success.\n"); + } +} + +void msgbox(struct sgi_form *form, w32 *text, s32 user, void (*callback)(s32)) +{ + assert(form != NULL); + + s32 r = 0; + sgi_msgbox_create(); + + if (!g_sgi_msgbox.initialized) { + r = g_sgi_msgbox.init(&g_sgi_msgbox); + printf("sgi_msgbox init.\n"); + } + + if (r == 0) { + sgi_ncpw2u(g_sgi_msgbox.text, text, COUNTOF(g_sgi_msgbox.text)); + form->msgbox = &g_sgi_msgbox; + g_sgi_msgbox.parent = form; + g_sgi_msgbox.x = form->wnd->x + (form->wnd->w - g_sgi_msgbox.w) / 2; + g_sgi_msgbox.y = form->wnd->y + (form->wnd->h - g_sgi_msgbox.h) / 2; + g_sgi_msgbox.redraw = 1; + g_sgi_msgbox.user = user; + g_sgi_msgbox.callback = callback; + } +} + +SDL_Surface *load_photo(struct passport_data *pass, s32 type) +{ + char file[MAX_PATH] = {0}; + char name[sizeof(pass->uid)]; + SDL_Surface *surface; + + if ((pass->visit & VALID_PASSPORT) != VALID_PASSPORT) { + return NULL; + } + + if (type == PHO_SAMPLE) { + sgi_ncpu2a(name, pass->uid, COUNTOF(pass->uid)); + sprintf(file, "%s/%s.jpg", PHOTO_SAMPLE_PATH, name); + } + else if (type == PHO_REAL) { + sprintf(file, "%s/%s.jpg", PHOTO_REAL_PATH, pass->photo); + } + + /* */ + printf("photo: %s\n", file); + surface = IMG_Load(file); + printf("surface: %p\n", surface); + + return surface; +} + +void unload_photo(struct sgi_photo *photo) +{ + if (photo->surface) { + SDL_FreeSurface(photo->surface); + } +} + +int alarm_ctrl(int on_off) +{ +// int fd; + int stat = -1; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + stat = ioctl(s_mfcard_fd, MFCARD_IOCTL_ALARM, &on_off); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +int power_ctrl(int on_off) +{ +// int fd; + int stat = -1; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + stat = ioctl(s_mfcard_fd, MFCARD_IOCTL_PW_CTRL, &on_off); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +int fpr_press_detect(void) +{ +// int fd; + int stat = 0; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_FPR_STATE, &stat) < 0) { + printf("MFCARD_IOCTL_FPR_STATE fail.\n"); + stat = 0; + } +// printf("fpr state: %d\n", stat); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +int card_start(void) +{ +// int fd; + int stat = 0; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_CARD_START, &stat) < 0) { + printf("MFCARD_IOCTL_CARD_START fail.\n"); + stat = 0; + } +// printf("card start: %d\n", stat); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +int card_state(void) +{ +// int fd; + int stat = 0; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_CARD_STATE, &stat) < 0) { + printf("MFCARD_IOCTL_CARD_STATE fail.\n"); + stat = 0; + } +// printf("card state: %d\n", stat); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +int get_card_id(void) +{ +// int fd; + int stat = 0; +// +// /* */ +// fd = open("/dev/mfcard", O_RDWR); +// if (fd == -1) { +// printf("Open /dev/mfcard fail.\n"); +// goto end; +// } + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_CARD_READ, &stat) < 0) { + printf("MFCARD_IOCTL_CARD_READ fail.\n"); + stat = -1; + } + printf("card id: 0x%x\n", stat); +// +//end: +// /* */ +// close(fd); + + return stat; +} + +s32 door_ctrl(s32 flag) +{ + int stat = 0; + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_DOOR_CTRL, &flag) < 0) { + printf("MFCARD_IOCTL_CARD_READ fail.\n"); + stat = -1; + } + + return stat; +} + +s32 get_door_fb(void) +{ + int stat = 0; + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_DOOR_FB, &stat) < 0) { + printf("MFCARD_IOCTL_DOOR_FB fail.\n"); + stat = -1; + } + + return stat; +} + +s32 get_pw_jc(void) +{ + int stat = 0; + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_PW_JC, &stat) < 0) { + printf("MFCARD_IOCTL_PW_JC fail.\n"); + stat = -1; + } + + return stat; +} + +s32 get_qwz1(void) +{ + int stat = 0; + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_QWZ1, &stat) < 0) { + printf("MFCARD_IOCTL_QWZ1 fail.\n"); + stat = -1; + } + + return stat; +} + +s32 get_qwz2(void) +{ + int stat = 0; + + /* */ + if (ioctl(s_mfcard_fd, MFCARD_IOCTL_QWZ2, &stat) < 0) { + printf("MFCARD_IOCTL_QWZ2 fail.\n"); + stat = -1; + } + + return stat; +} + +s32 mfcard_module_open(void) +{ + /* */ + s_mfcard_fd = open("/dev/mfcard", O_RDWR); + if (s_mfcard_fd == -1) { + printf("Open /dev/mfcard fail.\n"); + } + printf("Open /dev/mfcard ok.\n"); + + return 0; +} + +void mfcard_module_close(void) +{ + if (s_mfcard_fd != -1) { + close(s_mfcard_fd); + } +} + + + diff --git a/src/sgi_base_box.cpp b/src/sgi_base_box.cpp new file mode 100644 index 0000000..39e74fa --- /dev/null +++ b/src/sgi_base_box.cpp @@ -0,0 +1,224 @@ +#include "global_func.h" + +/* sgi-box default subroutine */ +s32 sgi_box_init_default(struct sgi_box *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 加载背景图片 */ + for (i = 0; i < 4; ++i) { + object->back[i].image = request_image(object->back[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->back[i].image) { + return FAIL; + } + } + + /* 加载字体 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_box_deinit_default(struct sgi_box *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 4; ++i) { + release_image(object->back[i].image); + object->back[i].image = NULL; + } + + /* 释放字体 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_box_frame_default(struct sgi_box *object) +{ + u32 i; + s32 index; + s16 x,y; + struct sgi_msg msg; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN) { + return 0; + } + + /* 判断那个按键被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + index = -1; + for (i = 0; i < BOX_NUMS; ++i) { + if ((x > object->x + object->cell[i].x + SPACE) + && (x < object->x + object->cell[i].x + object->cell[i].w - SPACE) + && (y > object->y + object->cell[i].y + SPACE) + && (y < object->y + object->cell[i].y + object->cell[i].h - SPACE)) { + index = i; + break; + } + } + + /* 无按键被按下,退出处理 */ + if (index == -1) { + return 0; + } + + if (CELL_VALID(object->cell[index].tag)) { + object->cell[index].state = 1 - object->cell[index].state; + } + if (object->down) { + object->down(object); + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + /* 置重绘标志 */ + object->redraw = 1; + + return 0; +} + +static void draw_cell_text(SDL_Surface *screen, SDL_Rect *rect, TTF_Font *font, + u16 *text) +{ + int x1 = 0; + int y1 = 0; + SDL_Surface *surface; + SDL_Color color = {255,255,255,0}; + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(font, text, color); + + if (!surface) { + return; + } + + /* 对齐处理 */ + if (rect->w > surface->w) { + x1 = (rect->w - surface->w) / 2; + } + rect->x = rect->x + x1; + if (rect->h > surface->h) { + y1 = (rect->h - surface->h) / 2; + } + rect->y = rect->y + y1; + rect->w = rect->w > surface->w ? surface->w : rect->w; + rect->h = surface->h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); +} + +void sgi_box_render_default(struct sgi_box *object, SDL_Surface *screen) +{ + u32 i; + SDL_Rect dst; + SDL_Rect src; + + /* 是否隐藏显示 */ + if (!(object->parent->redraw || object->redraw) || object->hide) { + return; + } + + /* 重绘背景图片 */ + dst.x = object->x; + dst.y = object->y; + dst.w = object->w; + dst.h = object->h; + SDL_BlitSurface(object->back[0].image, NULL, screen, &dst); + + /* 重绘cell */ + for (i = 0; i < BOX_NUMS; ++i) { + if (CELL_EMPTY(object->cell[i].tag)) { + src.x = object->cell[i].x; + src.y = object->cell[i].y; + src.w = object->cell[i].w; + src.h = object->cell[i].h; + + dst.x = object->x + src.x; + dst.y = object->y + src.y; + dst.w = src.w; + dst.h = src.h; + SDL_BlitSurface(object->back[3].image, &src, screen, &dst); + } + else if (CELL_BORROW(object->cell[i].tag)) { + src.x = object->cell[i].x; + src.y = object->cell[i].y; + src.w = object->cell[i].w; + src.h = object->cell[i].h; + + dst.x = object->x + src.x; + dst.y = object->y + src.y; + dst.w = src.w; + dst.h = src.h; + SDL_BlitSurface(object->back[2].image, &src, screen, &dst); + } + else if (object->cell[i].state) { + src.x = object->cell[i].x; + src.y = object->cell[i].y; + src.w = object->cell[i].w; + src.h = object->cell[i].h; + + dst.x = object->x + src.x; + dst.y = object->y + src.y; + dst.w = src.w; + dst.h = src.h; + SDL_BlitSurface(object->back[1].image, &src, screen, &dst); + } + } + + /* 重绘枪锁地址 */ + if (object->cell_addr) { + u16 buf[8] = {0}; + for (i = 0; i < BOX_NUMS; ++i) { + dst.x = object->x + object->cell[i].x; + dst.y = object->y + object->cell[i].y; + dst.w = object->cell[i].w; + dst.h = object->cell[i].h; + + sgi_sprintf16(buf, L"%03d", object->cell_addr[i]); + draw_cell_text(screen, &dst, object->font.font, buf); + } + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} + +void sgi_box_down_default(struct sgi_box *object) +{ + +} + +void sgi_box_up_default(struct sgi_box *object) +{ + +} diff --git a/src/sgi_base_button.cpp b/src/sgi_base_button.cpp new file mode 100644 index 0000000..8d87a88 --- /dev/null +++ b/src/sgi_base_button.cpp @@ -0,0 +1,175 @@ +#include "global_func.h" + +/* sgi-button default subroutine */ +s32 sgi_button_init_default(struct sgi_button *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 加载背景图片 */ + for (i = 0; i < 3; ++i) { + if (!object->back[i].name) { + continue; + } + object->back[i].image = request_image(object->back[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->back[i].image) { + return FAIL; + } + } + + /* 加载前景图片 */ + if (object->front.name) { + object->front.image = request_image(object->front.name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->front.image) { + return FAIL; + } + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_button_deinit_default(struct sgi_button *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 3; ++i) { + release_image(object->back[i].image); + object->back[i].image = NULL; + } + + /* 释放前景图片 */ + release_image(object->front.image); + object->front.image = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_button_frame_default(struct sgi_button *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + // test + //printf("button has a msg.\n"); + + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if ((x > object->x + SPACE) && (x < object->x + object->w - SPACE) + && (y > object->y + SPACE) && (y < object->y + object->h - SPACE)) { + keypress = 1; + } + + if (!keypress) { + /* 如果按键收到弹起消息,不管坐标是否在按键之内,都要取消被按下状态 */ + if (msg.type == SGI_MOUSEUP) { + object->state &= ~1; + object->redraw = 1; + } + + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + printf("sgi_mousedown.\n"); + if ((object->state & 2) == 0) { + play_effect(); + } + object->state |= 1; + object->redraw = 1; + if (object->down) { + object->down(object); + } + break; + + case SGI_MOUSEUP: + printf("sgi_mouseup.\n"); + if (object->up && object->state) { + object->up(object); + } + + object->state &= ~1; + object->redraw = 1; + break; + + default: + break; + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + return 0; +} + +void sgi_button_render_default(struct sgi_button *object, SDL_Surface *screen) +{ + SDL_Rect rect; + s32 index; + + if (!(object->parent->redraw || object->redraw) || object->hide) { + return; + } + + /* 重绘背景图片 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + if (object->state & 2) { + index = 2; + } + else { + index = object->state & 1; + } + if (object->back[index].image) { + SDL_BlitSurface(object->back[index].image, NULL, screen, &rect); + } + + /* 重绘前景图片 */ + if (object->front.image) { + SDL_BlitSurface(object->front.image, NULL, screen, &rect); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} + +void sgi_button_down_default(struct sgi_button *object) +{ + +} + +void sgi_button_up_default(struct sgi_button *object) +{ + +} + +void sgi_button_click_default(struct sgi_button *object) +{ + +} diff --git a/src/sgi_base_check.cpp b/src/sgi_base_check.cpp new file mode 100644 index 0000000..be4ff3e --- /dev/null +++ b/src/sgi_base_check.cpp @@ -0,0 +1,129 @@ +#include "global_func.h" + +/* sgi-check default subroutine */ +s32 sgi_check_init_default(struct sgi_check *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* */ + for (i = 0; i < 2; ++i) { + object->image[i].image = request_image(object->image[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->image[i].image) { + return FAIL; + } + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_check_deinit_default(struct sgi_check *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 2; ++i) { + release_image(object->image[i].image); + object->image[i].image = NULL; + } + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_check_frame_default(struct sgi_check *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if ((x > object->x + RADIO_SPACE) + && (x < object->x + object->w - RADIO_SPACE) + && (y > object->y + RADIO_SPACE) + && (y < object->y + object->h - RADIO_SPACE)) { + keypress = 1; + } + + if (!keypress) { + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + printf("check mousedown.\n"); + play_effect(); + object->state |= 1; + object->redraw = 1; + break; + + case SGI_MOUSEUP: + printf("check mouseup.\n"); + if (object->state) { + object->value = 1 - object->value; + object->redraw = 1; + + if (object->up) { + object->up(object); + } + } + + object->state &= ~1; + break; + + default: + break; + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + return 0; +} + +void sgi_check_render_default(struct sgi_check *object, SDL_Surface *screen) +{ + SDL_Rect rect; + s32 index = 0; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + /* 重绘背景图片 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + if (object->value) { + index = 1; + } + + if (object->image[index].image) { + SDL_BlitSurface(object->image[index].image, NULL, screen, &rect); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_edit.cpp b/src/sgi_base_edit.cpp new file mode 100644 index 0000000..b756770 --- /dev/null +++ b/src/sgi_base_edit.cpp @@ -0,0 +1,213 @@ +#include "global_func.h" + +/* sgi-edit default subroutine */ +s32 sgi_edit_init_default(struct sgi_edit *object) +{ + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 申请光标资源 */ + object->image.image = request_image(object->image.name, object->image.flags); + if (!object->image.image) { + return FAIL; + } + + /* 申请字体资源 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_edit_deinit_default(struct sgi_edit *object) +{ + /* 释放光标资源 */ + release_image(object->image.image); + object->image.image = NULL; + + /* 释放字体资源 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_edit_frame_default(struct sgi_edit *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 判断控件是否拥有焦点 */ + if (object->parent->focus_handle == object->handle) { + /* 光标闪烁 */ + if (SDL_GetTicks() > object->cursor_timer) { + object->cursor = 1 - object->cursor; + object->redraw = 1; + object->cursor_timer = SDL_GetTicks() + 500; + } + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + /* 输入内容处理 */ + struct sgi_msg &char_msg = object->parent->msg.front(); + if (char_msg.type == SGI_CHAR) { + if (!object->readonly) { + sgi_edit_insert_text(object, char_msg.lparam); + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + object->redraw = 1; + + } + } + else { + /* 无焦点不能拥有光标 */ + if (object->cursor) { + object->cursor = 0; + object->redraw = 1; + } + } + + /* 查看消息队列是否有按下消息 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type == SGI_MOUSEDOWN) { + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if ((x > object->x + EDIT_SPACE) + && (x < object->x + object->w - EDIT_SPACE) + && (y > object->y + EDIT_SPACE) + && (y < object->y + object->h - EDIT_SPACE)) { + keypress = 1; + } + + if (keypress) { + //printf("edit: sgi_mousedown.\n"); + object->parent->focus_handle = object->handle; + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + } + } + + return 0; +} + +void sgi_edit_render_default(struct sgi_edit *object, SDL_Surface *screen) +{ + int x1 = 0; + int y1 = 0; + int y2 = 0; + SDL_Rect rect; + SDL_Rect rect_cur; + SDL_Surface *surface; + + assert(object->font.font != NULL); + if (!(object->parent->redraw || object->redraw)) { + return; + } + + /* 用背景图像刷新文字范围 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->parent->wnd->image.image, &rect, screen, &rect); + + /* 无内容且不重绘文本层 */ + if (object->text[0] != 0) { + if (object->pwdchar) { + u32 i; + u32 len; + u16 text[64]; + + len = sgi_len16(object->text); + for (i = 0; i < len - 1; ++i) { + text[i] = (u16)L'*'; + } + text[i] = object->text[i]; + text[i + 1] = 0; + + surface = TTF_RenderUNICODE_Blended(object->font.font, + text, object->fcolor); + } + else { + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(object->font.font, + object->text, object->fcolor); + } + + if (!surface) { + return; + } + + /* 对齐处理 */ + if (object->w > surface->w) { + if (object->align == DT_CENTER) { + x1 = (object->w - surface->w) / 2; + } + else if (object->align == DT_RIGHT) { + x1 = (object->w - surface->w); + } + } + rect.x = object->x + x1; + if (object->h > surface->h) { + y1 = (object->h - surface->h) / 2; + } + rect.y = object->y + y1; + rect.w = object->w > surface->w ? surface->w : object->w; + rect.h = surface->h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, &rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); + + /* 记录字体长度以便重绘光标使用 */ + x1 = surface->w; + } + else { + x1 = 0; + } + + /* 是否需要重绘光标 */ + if (object->cursor) { + if (object->h > object->image.image->h) { + y1 = (object->h - object->image.image->h) / 2; + y2 = object->image.image->h; + } + else { + y1 = -2; + y2 = object->image.image->h - 2; + + } + rect_cur.x = object->x + x1; + rect_cur.y = object->y + y1; + rect_cur.w = object->image.image->w; + rect_cur.h = y2; + SDL_BlitSurface( object->image.image, NULL, screen, &rect_cur); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_form.cpp b/src/sgi_base_form.cpp new file mode 100644 index 0000000..a84e879 --- /dev/null +++ b/src/sgi_base_form.cpp @@ -0,0 +1,407 @@ +#include "global_func.h" + +s32 sgi_form_init_default(struct sgi_form *form) +{ + u32 i,r; + + if (form->initialized) { + return 0; + } + + for (i = 0; i < form->form.size(); ++i) { + switch (form->form[i]->type) { + case SGI_WINDOW: + r = form->form[i]->window.init(&form->form[i]->window); + if (r != 0) { + return FAIL; + } + break; + +// case SGI_PICTURE +// form->form[i].picture.init(form->form[i].window); +// break; + + case SGI_LABEL: + r = form->form[i]->label.init(&form->form[i]->label); + if (r != 0) { + return FAIL; + } + break; + + case SGI_EDIT: + r = form->form[i]->edit.init(&form->form[i]->edit); + if (r != 0) { + return FAIL; + } + break; + + case SGI_BUTTON: + r = form->form[i]->button.init(&form->form[i]->button); + if (r != 0) { + return FAIL; + } + break; + + case SGI_IME: + r = form->form[i]->ime.init(&form->form[i]->ime); + if (r != 0) { + return FAIL; + } + break; + + case SGI_BOX: + r = form->form[i]->box.init(&form->form[i]->box); + if (r != 0) { + return FAIL; + } + break; + + case SGI_GRID: + r = form->form[i]->grid.init(&form->form[i]->grid); + if (r != 0) { + return FAIL; + } + break; + + case SGI_RADIO: + r = form->form[i]->radio.init(&form->form[i]->radio); + if (r != 0) { + return FAIL; + } + break; + + case SGI_CHECK: + r = form->form[i]->check.init(&form->form[i]->check); + if (r != 0) { + return FAIL; + } + break; + + case SGI_UPDOWN: + r = form->form[i]->updown.init(&form->form[i]->updown); + if (r != 0) { + return FAIL; + } + break; + + case SGI_INDICATOR: + r = form->form[i]->indicator.init(&form->form[i]->indicator); + if (r != 0) { + return FAIL; + } + break; + + default: + break; + } + } + + form->initialized = 1; + + return 0; +} + +void sgi_form_deinit_default(struct sgi_form *form) +{ + u32 i; + + if (!form->initialized) { + return; + } + + for (i = 0; i < form->form.size(); ++i) { + switch (form->form[i]->type) { + case SGI_WINDOW: + form->form[i]->window.deinit(&form->form[i]->window); + break; + +// case SGI_PICTURE +// form->form[i].picture.init(form->form[i].window); +// break; + + case SGI_LABEL: + form->form[i]->label.deinit(&form->form[i]->label); + break; + + case SGI_EDIT: + form->form[i]->edit.deinit(&form->form[i]->edit); + break; + + case SGI_BUTTON: + form->form[i]->button.deinit(&form->form[i]->button); + break; + + case SGI_IME: + form->form[i]->ime.deinit(&form->form[i]->ime); + break; + + case SGI_BOX: + form->form[i]->box.deinit(&form->form[i]->box); + break; + + case SGI_GRID: + form->form[i]->grid.deinit(&form->form[i]->grid); + break; + + case SGI_RADIO: + form->form[i]->radio.deinit(&form->form[i]->radio); + break; + + case SGI_CHECK: + form->form[i]->check.deinit(&form->form[i]->check); + break; + + case SGI_UPDOWN: + form->form[i]->updown.deinit(&form->form[i]->updown); + break; + + case SGI_INDICATOR: + form->form[i]->indicator.deinit(&form->form[i]->indicator); + break; + + default: + break; + } + } +} + +s32 sgi_form_frame_default(struct sgi_form *form) +{ + u32 i; + + if (!form->initialized) { + return 0; + } + + /* 对话框处理 */ + if (form->msgbox) { + form->msgbox->frame(form->msgbox); + } + + /* 输入法处理 */ + if (form->ime) { + form->ime->frame(form->ime); + } + + /* 其他控件处理 */ + for (i = 0; i < form->form.size(); ++i) { + switch (form->form[i]->type) { + case SGI_WINDOW: + if (form->form[i]->window.frame) { + form->form[i]->window.frame(&form->form[i]->window); + } + break; + +// case SGI_PICTURE +// form->form[i].picture.init(form->form[i].window); +// break; + + case SGI_LABEL: + if (form->form[i]->label.frame) { + form->form[i]->label.frame(&form->form[i]->label); + } + break; + + case SGI_EDIT: + if (form->form[i]->edit.frame) { + form->form[i]->edit.frame(&form->form[i]->edit); + } + break; + + case SGI_BUTTON: + form->form[i]->button.frame(&form->form[i]->button); + break; + + case SGI_IME: + if (form->form[i]->ime.frame) { + form->form[i]->ime.frame(&form->form[i]->ime); + } + break; + + case SGI_BOX: + if (form->form[i]->box.frame) { + form->form[i]->box.frame(&form->form[i]->box); + } + break; + + case SGI_GRID: + if (form->form[i]->grid.frame) { + form->form[i]->grid.frame(&form->form[i]->grid); + } + break; + + case SGI_RADIO: + if (form->form[i]->radio.frame) { + form->form[i]->radio.frame(&form->form[i]->radio); + } + break; + + case SGI_CHECK: + if (form->form[i]->check.frame) { + form->form[i]->check.frame(&form->form[i]->check); + } + break; + + case SGI_UPDOWN: + if (form->form[i]->updown.frame) { + form->form[i]->updown.frame(&form->form[i]->updown); + } + break; + + case SGI_INDICATOR: + if (form->form[i]->indicator.frame) { + form->form[i]->indicator.frame(&form->form[i]->indicator); + } + break; + + default: + break; + } + } + + return 0; +} + +void sgi_form_render_default(struct sgi_form *form, SDL_Surface *screen) +{ + u32 i; + + if (!form->initialized) { + return; + } + + for (i = 0; i < form->form.size(); ++i) { + switch (form->form[i]->type) { + case SGI_WINDOW: + if (form->form[i]->window.render) { + form->form[i]->window.render(&form->form[i]->window, screen); + } + break; + + case SGI_PHOTO: + if (form->form[i]->photo.render) { + form->form[i]->photo.render(&form->form[i]->photo, screen); + } + break; + + case SGI_LABEL: + if (form->form[i]->label.render) { + form->form[i]->label.render(&form->form[i]->label, screen); + } + break; + + case SGI_EDIT: + if (form->form[i]->edit.render) { + form->form[i]->edit.render(&form->form[i]->edit, screen); + } + break; + + case SGI_BUTTON: + if (form->form[i]->button.render) { + form->form[i]->button.render(&form->form[i]->button, screen); + } + break; + + case SGI_IME: + if (form->form[i]->ime.render) { + form->form[i]->ime.render(&form->form[i]->ime, screen); + } + break; + + case SGI_BOX: + if (form->form[i]->box.render) { + form->form[i]->box.render(&form->form[i]->box, screen); + } + break; + + case SGI_GRID: + if (form->form[i]->grid.render) { + form->form[i]->grid.render(&form->form[i]->grid, screen); + } + break; + + case SGI_RADIO: + if (form->form[i]->radio.render) { + form->form[i]->radio.render(&form->form[i]->radio, screen); + } + break; + + case SGI_CHECK: + if (form->form[i]->check.render) { + form->form[i]->check.render(&form->form[i]->check, screen); + } + break; + + case SGI_UPDOWN: + if (form->form[i]->updown.render) { + form->form[i]->updown.render(&form->form[i]->updown, screen); + } + break; + + case SGI_INDICATOR: + if (form->form[i]->indicator.render) { + form->form[i]->indicator.render(&form->form[i]->indicator, screen); + } + break; + + default: + break; + } + } + + /* 输入法模块处理 */ + if (form->ime) { + form->ime->render(form->ime, screen); + } + + /* 对话框显示 */ + if (form->msgbox) { + if (form->dirty) { + form->msgbox->redraw = 1; + } + form->msgbox->render(form->msgbox, screen); + } + + /* 更新显示 */ + if (form->dirty) { + SDL_UpdateRect(screen, form->x1, form->y1, + form->x2 - form->x1, form->y2 - form->y1); + + form->dirty = 0; + form->redraw = 0; + form->x1 = X_RES; + form->y1 = Y_RES; + form->x2 = 0; + form->y2 = 0; + } +} + +void form_memset(struct sgi_form *form) +{ + form->name = NULL; + form->form.clear(); + form->msg.clear(); + form->wnd = NULL; + form->ime = NULL; + form->msgbox = NULL; + + form->initialized = 0; + form->redraw = 0; + form->dirty = 0; + form->x1 = 0; + form->x2 = 0; + form->y1 = 0; + form->y2 = 0; + + form->init = NULL; + form->deinit = NULL; + form->frame = NULL; + form->render = NULL; + + form->enter = NULL; + form->exit = NULL; + + form->add = NULL; + form->del = NULL; + form->sort = NULL; +} diff --git a/src/sgi_base_grid.cpp b/src/sgi_base_grid.cpp new file mode 100644 index 0000000..09b9db7 --- /dev/null +++ b/src/sgi_base_grid.cpp @@ -0,0 +1,267 @@ +#include "global_func.h" + +/* sgi-grid default subroutine */ +s32 sgi_grid_init_default(struct sgi_grid *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 加载图片 */ + object->back.image = request_image(object->back.name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->back.image) { + return FAIL; + } + + object->action.image = request_image(object->action.name, + IMG_OPTIMIZE | IMG_ALPHA); + + /* 加载字体 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_grid_deinit_default(struct sgi_grid *object) +{ + u32 i; + + /* 释放图片 */ + release_image(object->back.image); + object->back.image = NULL; + release_image(object->action.image); + object->action.image = NULL; + + /* 释放字体 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +static void grid_radio_handle(struct sgi_grid *object, s32 index) +{ + s32 pos; + s32 i; + s32 old_val = object->cells[index].val; + + pos = index / object->col * object->col; + printf("pos: %d, index: %d\n", pos, index); + for (i = pos; i < pos + object->col; ++i) { + if (object->cells[i].type == GRID_RADIO) { + if (i != index) { + object->cells[i].val = 0; + } + else { + object->cells[i].val = 1; + } + } + } + + if (object->cells[index].val != old_val) { + object->changed = 1; + } +} + +static void grid_button_handle(struct sgi_grid *object, s32 index) +{ + s32 row = index / object->col; + + if (object->up) { + printf("grid row (2): %d\n", row); + object->up(object, row); + } +} + +s32 sgi_grid_frame_default(struct sgi_grid *object) +{ + s32 i,j; + s32 index,pos; + s16 x,y; + struct sgi_msg msg; + + /* 只读表格不响应按键动作 */ + if (object->readonly) { + return 0; + } + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + /* 判断那个按键被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + index = -1; + for (i = 0; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + pos = i * object->col + j; + if ((x > object->cells[pos].x) + && (x < object->cells[pos].x + object->cells[pos].w) + && (y > object->cells[pos].y) + && (y < object->cells[pos].y + object->cells[pos].h)) { + index = pos; + break; + } + } + } + + /* 无按键被按下,退出处理 */ + if (index == -1) { + if (msg.type == SGI_MOUSEUP) { + for (i = 0; i < object->col * object->row; ++i) { + object->cells[i].state &= ~1; + } + } + + return 0; + } + + /* */ + if (object->cells[index].type == GRID_STRING) { + return 0; + } + + if (msg.type == SGI_MOUSEDOWN) { + object->cells[index].state |= 1; + } + else { + if (object->cells[index].state) { + if (object->cells[index].type == GRID_RADIO) { + grid_radio_handle(object, index); + } + else if (object->cells[index].type == GRID_BUTTON) { + grid_button_handle(object, index); + } + } + + for (i = 0; i < object->col * object->row; ++i) { + object->cells[i].state &= ~1; + } + } + + /* 置重绘标志 */ + object->redraw = 1; + + return 0; +} + +static void draw_cell_text(SDL_Surface *screen, SDL_Rect *rect, TTF_Font *font, + u16 *text) +{ + int x1 = 0; + int y1 = 0; + SDL_Surface *surface; + SDL_Color color = {0,0,0,0}; + + if (!text || text[0] == 0) { + return; + } + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(font, text, color); + + if (!surface) { + return; + } + + /* 对齐处理 */ + if (rect->w > surface->w) { + x1 = (rect->w - surface->w) / 2; + } + rect->x = rect->x + x1; + if (rect->h > surface->h) { + y1 = (rect->h - surface->h + 1) / 2; + } + rect->y = rect->y + y1; + rect->w = rect->w > surface->w ? surface->w : rect->w; + rect->h = surface->h; + printf("surface->h: %d, y1: %d\n", surface->h, y1); + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); +} + +void sgi_grid_render_default(struct sgi_grid *object, SDL_Surface *screen) +{ + s32 i; + SDL_Rect dst; + SDL_Rect src; + + /* 是否隐藏显示 */ + if (!(object->parent->redraw || object->redraw)) { + return; + } + + /* 重绘背景图片 */ + dst.x = object->x; + dst.y = object->y; + dst.w = object->w; + dst.h = object->h; + SDL_BlitSurface(object->back.image, NULL, screen, &dst); + + /* 重绘cell */ + for (i = 0; i < object->col * object->row; ++i) { + switch (object->cells[i].type) { + case GRID_STRING: + dst.x = object->cells[i].x; + dst.y = object->cells[i].y; + dst.w = object->cells[i].w; + dst.h = object->cells[i].h; + draw_cell_text(screen, &dst, object->font.font, + object->cells[i].string); + break; + + case GRID_RADIO: + if (object->cells[i].val) { + dst.x = object->cells[i].x; + dst.y = object->cells[i].y; + dst.w = object->cells[i].w; + dst.h = object->cells[i].h; + SDL_BlitSurface(object->action.image, NULL, + screen, &dst); + } + break; + + case GRID_BUTTON: + if (object->cells[i].state & 1) { + dst.x = object->cells[i].x; + dst.y = object->cells[i].y; + dst.w = object->cells[i].w; + dst.h = object->cells[i].h; + SDL_BlitSurface(object->action.image, NULL, + screen, &dst); + } + break; + + default: + break; + } + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} + diff --git a/src/sgi_base_ime.cpp b/src/sgi_base_ime.cpp new file mode 100644 index 0000000..e829baf --- /dev/null +++ b/src/sgi_base_ime.cpp @@ -0,0 +1,452 @@ +#include "global_func.h" + +/* sgi-ime default subroutine */ +s32 sgi_ime_init_default(struct sgi_ime *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 加载背景图片 */ + for (i = 0; i < 2; ++i) { + object->back[i].image = request_image(object->back[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->back[i].image) { + return FAIL; + } + } + + /* 加载字体 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_ime_deinit_default(struct sgi_ime *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 2; ++i) { + release_image(object->back[i].image); + object->back[i].image = NULL; + } + + /* 释放字体 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_ime_frame_default(struct sgi_ime *object) +{ + u32 i; + s32 index,pos; + s16 x,y; + u16 ch; + + /* 查看消息队列 */ + if (object->hide || object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + /* 判断那个按键被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + + /* 在中文模式下扫描文字选择区 */ + do { + if (object->mode != IME_PINYIN) { + break; + } + + index = -1; + for (i = 0; i < SELECTOR_NUMS; ++i) { + if ((x > object->x + object->selector[i].x) + && (x < object->x + object->selector[i].x + object->selector[i].w) + && (y > object->y + object->selector[i].y) + && (y < object->y + object->selector[i].y + object->selector[i].h)) { + index = i; + } + } + + //printf("selector: %d\n", index); + + if (index == -1) { + break; + } + + if (msg.type == SGI_MOUSEUP) { + for (i = 0; i < SELECTOR_NUMS; ++i) { + object->selector[i].state &= ~1; + } + } + else { + switch (index) { + case 0: /* 上一页 */ + if (object->chinese.page > 0) { + object->chinese.page--; + } + else { + object->chinese.page = 0; + } + object->selector[index].state |= 1; + break; + + case 1: /*拼音显示区 */ + break; + + case 2: /* 选字区 */ + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + pos = object->chinese.page * 7 + (index - 2); + if (pos < object->chinese.count) { + struct sgi_msg m; + m.type = SGI_CHAR; + m.wparam = 0; + m.lparam = (u16)object->chinese.chinese[pos]; + object->parent->msg.push_back(m); + + /* 清除选择面板 */ + memset(&object->chinese, 0, sizeof(struct sgi_ime_chinese)); + } + object->selector[index].state |= 1; + break; + + case 9: /* 下一页 */ + if (object->chinese.page < object->chinese.count / 7) { /* 7个选字框 */ + object->chinese.page++; + } + else { + object->chinese.page = object->chinese.count / 7; + } + object->selector[index].state |= 1; + break; + + default: + break; + } + } + + goto finished; + + } while (0); + + /* 扫描普通按键区 */ + index = -1; + for (i = 0; i < KEY_NUMS; ++i) { + if ((x > object->key[i].x + object->x + SPACE) + && (x < object->x + object->key[i].x + object->key[i].w - SPACE) + && (y > object->y + object->key[i].y + SPACE) + && (y < object->y + object->key[i].y + object->key[i].h - SPACE)) { + index = i; + //printf("key press: %d\n", index); + break; + } + } + + /* 无按键被按下,退出处理 */ + if (index == -1) { + /* 如果按键收到弹起消息,不管坐标是否在按键之内,都要取消被按下状态 */ + if (msg.type == SGI_MOUSEUP) { + for (i = 0; i < KEY_NUMS; ++i) { + object->key[i].state &= ~1; + object->redraw = 1; + } + } + + /* 如果坐标落在输入法框范围内, 则移除按键消息,防止后面程序响应 */ + if (x > object->x + 78 && x < object->x + object->w - 78 + && y > object->y && y < object->y + object->h) { + object->parent->msg.pop_front(); + } + + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + play_effect(); + object->state |= 1; + object->key[index].state |= 1; + if (object->mode == IME_PINYIN) { + ch = object->word[object->mode].word[index]; + if (ch == 0x0008) { /* del */ + if (object->chinese.syllables[0] == 0) { + struct sgi_msg m; + m.type = SGI_CHAR; + m.wparam = 0; + m.lparam = 0x0008; + object->parent->msg.push_back(m); + } + else { + sgi_rdel16(object->chinese.syllables, + COUNTOF(object->chinese.syllables)); + } + } + else if (ch != 0x001b) { + //char buf[8] = {0}; + //printf("syllables ch: %x\n", ch); + if (ch >= 'a' && ch <= 'z') { + sgi_ncat16(object->chinese.syllables, ch, 6); + } + //printf("syllables: %s\n", sgi_cpu2a(buf, object->chinese.syllables)); + } + + if (object->chinese.syllables[0] == 0) { /* 无拼音输入 */ + memset(&object->chinese, 0, sizeof(struct sgi_ime_chinese)); + } + else { + object->chinese.chinese = decode_syllables(object->chinese.syllables); + if (object->chinese.chinese) { + object->chinese.count = wcslen(object->chinese.chinese); + } + else { + object->chinese.count = 0; + } + object->chinese.page = 0; + } + } + else { + if (object->word[object->mode].word[index] != 0x001B){ + struct sgi_msg m; + m.type = SGI_CHAR; + m.wparam = 0; + m.lparam = object->word[object->mode].word[index]; + object->parent->msg.push_back(m); + } + } + + if (object->down) { + object->down(object); + } + break; + + case SGI_MOUSEUP: + object->state &= ~1; + object->key[index].state &= ~1; + + /* 判断是否切换输入法按键 */ + if (object->word[object->mode].word[index] == 0x001B) { + object->mode++; + if (object->mode == IME_PINYIN) { + /* 清零中文输入法缓冲区 */ + memset(&object->chinese, 0, sizeof(struct sgi_ime_chinese)); + } + if (object->mode > IME_PINYIN) { + object->mode = IME_CHAR; + } + } + + if (object->up) { + object->up(object); + } + break; + + default: + break; + } + +finished: + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + /* 置重绘标志 */ + object->redraw = 1; + + return 0; +} + +static void draw_key_text(SDL_Surface *screen, SDL_Rect *rect, TTF_Font *font, + const u16 *text) +{ + int x1 = 0; + int y1 = 0; + SDL_Surface *surface; + SDL_Color color = {0,0,0,0}; + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(font, text, color); + + if (!surface) { + return; + } + + /* 对齐处理 */ + if (rect->w > surface->w) { + x1 = (rect->w - surface->w) / 2; + } + rect->x = rect->x + x1; + if (rect->h > surface->h) { + y1 = (rect->h - surface->h) / 2; + } + rect->y = rect->y + y1; + rect->w = rect->w > surface->w ? surface->w : rect->w; + rect->h = surface->h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); +} + +void sgi_ime_render_default(struct sgi_ime *object, SDL_Surface *screen) +{ + u32 i; + s32 index; + SDL_Rect rect; + SDL_Rect dest; + + /* 是否隐藏显示 */ + if (!(object->parent->redraw || object->redraw) || object->hide) { + return; + } + + /* 重绘背景图片 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->back[0].image, NULL, screen, &rect); + + if (object->mode == IME_PINYIN) { + index = -1; + for (i = 0; i < SELECTOR_NUMS; ++i) { + if (object->selector[i].state & 1) { + index = i; + break; + } + } + + //printf("render py: %d\n", index); + if (index != -1) { + rect.x = object->selector[index].x; + rect.y = object->selector[index].y; + rect.w = object->selector[index].w; + rect.h = object->selector[index].h; + + dest.x = object->x + rect.x; + dest.y = object->y + rect.y; + dest.w = rect.w; + dest.h = rect.h; + + i = SDL_BlitSurface(object->back[1].image, &rect, screen, &dest); + if (i != 0) { + printf("draw err: %s\n", SDL_GetError() ); + } + } + + /* 重绘选择区文字 */ + u16 buf[4]; + s32 pos; + + /* 重绘 << */ + buf[0] = '<'; + buf[1] = '<'; + buf[2] = 0; + rect.x = object->x + object->selector[0].x; + rect.y = object->y + object->selector[0].y; + rect.w = object->selector[0].w; + rect.h = object->selector[0].h; + draw_key_text(screen, &rect, object->font.font, buf); + + /* 重绘 >> */ + buf[0] = '>'; + buf[1] = '>'; + buf[2] = 0; + rect.x = object->x + object->selector[9].x; + rect.y = object->y + object->selector[9].y; + rect.w = object->selector[9].w; + rect.h = object->selector[9].h; + draw_key_text(screen, &rect, object->font.font, buf); + + /* 重绘音节 */ + rect.x = object->x + object->selector[1].x; + rect.y = object->y + object->selector[1].y; + rect.w = object->selector[1].w; + rect.h = object->selector[1].h; + draw_key_text(screen, &rect, object->font.font, object->chinese.syllables); + + /* 重绘拼音汉字 */ + for (i = 0; i < 7; ++i) { + pos = object->chinese.page * 7 + i; + if (pos > object->chinese.count - 1) { + break; + } + + buf[0] = (u16)object->chinese.chinese[pos]; + buf[1] = 0; + rect.x = object->x + object->selector[i + 2].x; + rect.y = object->y + object->selector[1 + 2].y; + rect.w = object->selector[i + 2].w; + rect.h = object->selector[i + 2].h; + draw_key_text(screen, &rect, object->font.font, buf); + } + } + + /* 重绘被按下按键 */ + if (object->state & 1) { + index = -1; + for (i = 0; i < KEY_NUMS; ++i) { + if (object->key[i].state & 1) { + index = i; + //printf("key redraw: %d\n", index); + break; + } + } + if (index != -1) { + rect.x = object->key[index].x; + rect.y = object->key[index].y; + rect.w = object->key[index].w; + rect.h = object->key[index].h; + + dest.x = object->x + object->key[index].x; + dest.y = object->y + object->key[index].y; + dest.w = object->key[index].w; + dest.h = object->key[index].h; + + i = SDL_BlitSurface(object->back[1].image, &rect, screen, &dest); + if (i != 0) { + printf("draw err: %s\n", SDL_GetError() ); + } + } + } + + /* 重绘按键文字 */ + for (i = 0; i < KEY_NUMS; ++i) { + rect.x = object->x + object->key[i].x; + rect.y = object->y + object->key[i].y; + rect.w = object->key[i].w; + rect.h = object->key[i].h; + draw_key_text(screen, &rect, object->font.font, + object->caption[object->mode].text[i]); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} + diff --git a/src/sgi_base_indicator.cpp b/src/sgi_base_indicator.cpp new file mode 100644 index 0000000..3f6bd12 --- /dev/null +++ b/src/sgi_base_indicator.cpp @@ -0,0 +1,65 @@ +#include "global_func.h" + +/* sgi-picture default subroutine */ +s32 sgi_indicator_init_default(struct sgi_indicator *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 申请资源 */ + for (i = 0; i < 2; ++i) { + object->image[i].image = request_image(object->image[i].name, + object->image[i].flags); + } + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_indicator_deinit_default(struct sgi_indicator *object) +{ + u32 i; + + /* 释放资源 */ + for (i = 0; i < 2; ++i) { + release_image(object->image[i].image); + object->image[i].image = NULL; + } + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_indicator_frame_default(struct sgi_indicator *object) +{ + return 0; +} + +void sgi_indicator_render_default(struct sgi_indicator *object, SDL_Surface *screen) +{ + SDL_Rect rect; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + if (object->image[object->state & 1].image) { + SDL_BlitSurface(object->image[object->state & 1].image, NULL, + screen, &rect); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_label.cpp b/src/sgi_base_label.cpp new file mode 100644 index 0000000..0c7675c --- /dev/null +++ b/src/sgi_base_label.cpp @@ -0,0 +1,95 @@ +#include "global_func.h" + +/* sgi-label default subroutine */ +s32 sgi_label_init_default(struct sgi_label *object) +{ + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 申请资源 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_label_deinit_default(struct sgi_label *object) +{ + /* 释放资源 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_label_frame_default(struct sgi_label *object) +{ + return 0; +} + +void sgi_label_render_default(struct sgi_label *object, SDL_Surface *screen) +{ + int x1 = 0; + int y1 = 0; + SDL_Rect rect; + SDL_Surface *surface; + + assert(object->font.font != NULL); + if (!(object->parent->redraw || object->redraw)) { + return; + } + + if (object->caption[0] == 0) { /* Caption为空 */ + return; + } + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(object->font.font, object->caption, + object->fcolor); + if (!surface) { + return; + } + + /* 用背景图像刷新文字范围 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->parent->wnd->image.image, &rect, screen, &rect); + + /* 对齐处理 */ + if (object->w > surface->w) { + if (object->align == DT_CENTER) { + x1 = (object->w - surface->w) / 2; + } + else if (object->align == DT_RIGHT) { + x1 = (object->w - surface->w); + } + } + rect.x = object->x + x1; + if (object->h > surface->h) { + y1 = (object->h - surface->h) / 2; + } + rect.y = object->y + y1; + rect.w = object->w > surface->w ? surface->w : object->w; + rect.h = surface->h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, &rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_msgbox.cpp b/src/sgi_base_msgbox.cpp new file mode 100644 index 0000000..738c150 --- /dev/null +++ b/src/sgi_base_msgbox.cpp @@ -0,0 +1,231 @@ +#include "global_func.h" + +/* sgi-label default subroutine */ +static void release_msgbox(struct sgi_msgbox *object) +{ + object->parent->redraw = 1; + object->parent->msgbox = NULL; + + if (object->callback) { + object->callback(object->user); + } +} + +s32 sgi_msgbox_init_default(struct sgi_msgbox *object) +{ + s32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 加载背景和提示图片 */ + for (i = 0; i < 4; ++i) { + object->image[i].image = request_image(object->image[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + } + if (!object->image[0].image || !object->image[2].image + || !object->image[3].image) { /* 背景图片不能为空 */ + return FAIL; + } + + printf("msgbox request font.\n"); + /* 加载字体 */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 根据背景图片设置尺寸 */ + object->w = object->image[0].image->w; + object->h = object->image[0].image->h; + object->button.w = object->image[2].image->w; + object->button.h = object->image[2].image->h; + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_msgbox_deinit_default(struct sgi_msgbox *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 2; ++i) { + release_image(object->image[i].image); + object->image[i].image = NULL; + } + + /* 释放字体 */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_msgbox_frame_default(struct sgi_msgbox *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + object->parent->msg.pop_front(); + return 0; + } + + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if (x > object->x + object->button.x + && x < object->x + object->button.x + object->button.w + && y > object->y + object->button.y + && y < object->y + object->button.y + object->button.h) { + keypress = 1; + } + + if (!keypress) { + /* 如果按键收到弹起消息,不管坐标是否在按键之内,都要取消被按下状态 */ + if (msg.type == SGI_MOUSEUP) { + object->button.state &= ~1; + object->redraw = 1; + } + + object->parent->msg.pop_front(); + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + play_effect(); + object->button.state |= 1; + object->redraw = 1; + + object->parent->msg.pop_front(); + break; + + case SGI_MOUSEUP: + object->button.state &= ~1; + object->redraw = 1; + + /* 清空消息队列 */ + object->parent->msg.clear(); + release_msgbox(object); + break; + + default: + break; + } + +#if 0 + s16 x,y; + + /* 查看消息队列 */ + while (!object->parent->msg.empty()) { + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type == SGI_MOUSEDOWN) { + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if (x > object->x + object->button->x + && x < object->x + object-button->w + && y > object->y + object->button->y + && y < object->y + object-button->h) { + + /* 清空消息队列 */ + object->parent->msg.clear(); + + release_msgbox(object); + break; + } + } + + object->parent->msg.pop_front(); + } +#endif + + + return 0; +} + +void sgi_msgbox_render_default(struct sgi_msgbox *object, SDL_Surface *screen) +{ + int x1 = 0; + int y1 = 0; + SDL_Rect rect; + SDL_Rect src; + SDL_Color color = {0, 0, 0, 0}; + SDL_Surface *surface; + + assert(object->font.font != NULL); + if (!(object->parent->redraw || object->redraw)) { + return; + } + + if (object->text == NULL) { /* Caption为空 */ + return; + } + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(object->font.font, object->text, color); + if (!surface) { + return; + } + + /* 用背景图像刷新文字范围 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->image[0].image, NULL, screen, &rect); + + /* 按键图像 */ + rect.x = object->x + object->button.x; + rect.y = object->y + object->button.y; + rect.w = object->button.w; + rect.h = object->button.h; + if (object->button.state & 1) { + SDL_BlitSurface(object->image[3].image, NULL, screen, &rect); + } + else { + SDL_BlitSurface(object->image[2].image, NULL, screen, &rect); + } + + /* 对齐处理 */ + if (object->w > surface->w) { + x1 = (object->w - surface->w) / 2; + } + + if (object->h > surface->h) { + y1 = (object->h - surface->h - 70) / 2; + } + + rect.x = object->x + x1; + rect.y = object->y + y1; + rect.w = object->w > surface->w ? surface->w : object->w; + rect.h = surface->h; + + src.x = 0; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, &src, screen, &rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_picture.cpp b/src/sgi_base_picture.cpp new file mode 100644 index 0000000..3f4e755 --- /dev/null +++ b/src/sgi_base_picture.cpp @@ -0,0 +1,82 @@ +#include "global_func.h" + +/* sgi-picture default subroutine */ +s32 sgi_picture_init_default(struct sgi_picture *object) +{ + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 申请资源 */ + object->image.image = request_image(object->image.name, object->image.flags); + if (!object->image.image) { + return FAIL; + } + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_picture_deinit_default(struct sgi_picture *object) +{ + /* 释放资源 */ + release_image(object->image.image); + object->image.image = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_picture_frame_default(struct sgi_picture *object) +{ + return 0; +} + +void sgi_picture_render_default(struct sgi_picture *object, SDL_Surface *screen) +{ + SDL_Rect rect; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->image.image, NULL, screen, &rect); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} + +void sgi_photo_render_default(struct sgi_photo *object, SDL_Surface *screen) +{ + SDL_Rect dst; + SDL_Rect src; + + if (!(object->parent->redraw || object->redraw) || !object->surface) { + return; + } + + printf("photo redraw.\n"); + dst.x = object->x; + dst.y = object->y; + dst.w = object->w; + dst.h = object->h; + src.x = 0; + src.y = 0; + src.w = dst.w; + src.h = dst.h; + SDL_BlitSurface(object->surface, &src, screen, &dst); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_radio.cpp b/src/sgi_base_radio.cpp new file mode 100644 index 0000000..bc1cdd7 --- /dev/null +++ b/src/sgi_base_radio.cpp @@ -0,0 +1,146 @@ +#include "global_func.h" + +/* sgi-check default subroutine */ +s32 sgi_radio_init_default(struct sgi_radio *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* */ + for (i = 0; i < 2; ++i) { + object->image[i].image = request_image(object->image[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->image[i].image) { + return FAIL; + } + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_radio_deinit_default(struct sgi_radio *object) +{ + u32 i; + + /* 释放背景图片 */ + for (i = 0; i < 2; ++i) { + release_image(object->image[i].image); + object->image[i].image = NULL; + } + + /* 重置初始标志 */ + object->initialized = 0; +} + +static void radio_up(struct sgi_radio *object) +{ + u32 i; + + for (i = 0; i < object->parent->form.size(); ++i) { + if (object->parent->form[i]->type != SGI_RADIO) { + continue; + } + + if (object->parent->form[i]->radio.handle != object->handle) { + object->parent->form[i]->radio.value = 0; + } + else { + object->parent->form[i]->radio.value = 1; + } + object->parent->form[i]->radio.redraw = 1; + } +} + +s32 sgi_radio_frame_default(struct sgi_radio *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if ((x > object->x + RADIO_SPACE) + && (x < object->x + object->w - RADIO_SPACE) + && (y > object->y + RADIO_SPACE) + && (y < object->y + object->h - RADIO_SPACE)) { + keypress = 1; + } + + if (!keypress) { + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + printf("radio mousedown.\n"); + object->state |= 1; + break; + + case SGI_MOUSEUP: + printf("radio mouseup.\n"); + if (object->state) { + radio_up(object); + object->redraw = 1; + + if (object->up) { + object->up(object); + } + } + + object->state &= ~1; + break; + + default: + break; + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + return 0; +} + +void sgi_radio_render_default(struct sgi_radio *object, SDL_Surface *screen) +{ + SDL_Rect rect; + s32 index = 0; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + /* 重绘背景图片 */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + if (object->value) { + index = 1; + } + + if (object->image[index].image) { + SDL_BlitSurface(object->image[index].image, NULL, screen, &rect); + } + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_updown.cpp b/src/sgi_base_updown.cpp new file mode 100644 index 0000000..6778034 --- /dev/null +++ b/src/sgi_base_updown.cpp @@ -0,0 +1,229 @@ +#include "global_func.h" + +/* sgi-updown default subroutine */ +s32 sgi_updown_init_default(struct sgi_updown *object) +{ + u32 i; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* image */ + for (i = 0; i < 2; ++i) { + object->image[i].image = request_image(object->image[i].name, + IMG_OPTIMIZE | IMG_ALPHA); + if (!object->image[i].image) { + return FAIL; + } + } + + /* font */ + object->font.font = request_font(object->font.name, object->font.size); + if (!object->font.font) { + return FAIL; + } + + /* 置初始化标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_updown_deinit_default(struct sgi_updown *object) +{ + u32 i; + + /* image */ + for (i = 0; i < 2; ++i) { + release_image(object->image[i].image); + object->image[i].image = NULL; + } + + /* font */ + release_font(object->font.font); + object->font.font = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_updown_frame_default(struct sgi_updown *object) +{ + s16 x,y; + s32 keypress = 0; + + /* 查看消息队列 */ + if (object->parent->msg.empty()) { + return 0; + } + + struct sgi_msg &msg = object->parent->msg.front(); + if (msg.type != SGI_MOUSEDOWN && msg.type != SGI_MOUSEUP) { + return 0; + } + + /* 判断按键是否被按下 */ + x = msg.lparam & 0xffff; + y = msg.lparam >> 16; + if ((x > object->x) + && (x < object->x + (object->w - object->tw) / 2) + && (y > object->y) + && (y < object->y + object->h)) { + keypress = 1; + } + else if ((x > object->x + (object->w + object->tw) / 2) + && (x < object->x + object->w) + && (y > object->y) + && (y < object->y + object->h)) { + keypress = 2; + } + + if (!keypress) { + /* 如果按键收到弹起消息,不管坐标是否在按键之内,都要取消被按下状态 */ + if (msg.type == SGI_MOUSEUP) { + object->state[0] &= ~1; + object->state[1] &= ~1; + object->redraw = 1; + } + return 0; + } + + switch (msg.type) { + case SGI_MOUSEDOWN: + printf("updown mousedown.\n"); + object->state[keypress - 1] |= 1; + object->redraw = 1; + break; + + case SGI_MOUSEUP: + printf("updown mouseup.\n"); + if (object->state[0]) { + object->value--; + } + else if (object->state[1]) { + object->value++; + } + object->redraw = 1; + object->state[0] &= ~1; + object->state[1] &= ~1; + break; + + default: + break; + } + + /* 移除已经处理的消息 */ + object->parent->msg.pop_front(); + + return 0; +} + +static void draw_text(SDL_Surface *screen, SDL_Rect *rect, TTF_Font *font, + u16 *text) +{ + int x1 = 0; + int y1 = 0; + SDL_Surface *surface; + SDL_Color color = {0,0,0,0}; + + /* 字体图形生成 */ + surface = TTF_RenderUNICODE_Blended(font, text, color); + + if (!surface) { + return; + } + + /* 对齐处理 */ + if (rect->w > surface->w) { + x1 = (rect->w - surface->w) / 2; + } + rect->x = rect->x + x1; + if (rect->h > surface->h) { + y1 = (rect->h - surface->h) / 2; + } + rect->y = rect->y + y1; + rect->w = rect->w > surface->w ? surface->w : rect->w; + rect->h = surface->h; + + /* 将字体图形渲染到目标 */ + SDL_BlitSurface(surface, NULL, screen, rect); + + /* 释放字体图形资源 */ + SDL_FreeSurface(surface); +} + +void sgi_updown_render_default(struct sgi_updown *object, SDL_Surface *screen) +{ + SDL_Rect rect; + SDL_Rect src; + u16 text[16]; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + /* */ + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + if (object->image[0].image) { + SDL_BlitSurface(object->image[0].image, NULL, screen, &rect); + } + + /* */ + if (object->state[0]) { + rect.x = object->x; + rect.y = object->y; + rect.w = (object->w - object->tw) / 2; + rect.h = object->h; + src.x = 0; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + } + else if (object->state[1]) { + rect.x = object->x + (object->w + object->tw) / 2; + rect.y = object->y; + rect.w = (object->w - object->tw ) / 2; + rect.h = object->h; + src.x = (object->w + object->tw) / 2; + src.y = 0; + src.w = rect.w; + src.h = rect.h; + } + if (object->image[1].image) { + SDL_BlitSurface(object->image[1].image, &src, screen, &rect); + } + + /* draw font */ + rect.x = object->x; + rect.y = object->y; + rect.w = (object->w - object->tw) / 2; + rect.h = object->h; + text[0] = (u16)L'-'; + text[1] = 0; + draw_text(screen, &rect, object->font.font, text); + + rect.x = object->x + (object->w + object->tw) / 2; + rect.y = object->y; + rect.w = (object->w - object->tw ) / 2; + rect.h = object->h; + text[0] = (u16)L'+'; + text[1] = 0; + draw_text(screen, &rect, object->font.font, text); + + rect.x = object->x + (object->w - object->tw) / 2; + rect.y = object->y; + rect.w = object->tw; + rect.h = object->h; + sgi_sprintf16(text, L"%d", object->value); + draw_text(screen, &rect, object->font.font, text); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_base_window.cpp b/src/sgi_base_window.cpp new file mode 100644 index 0000000..6c52839 --- /dev/null +++ b/src/sgi_base_window.cpp @@ -0,0 +1,104 @@ +#include "global_func.h" + +/* sgi-window default subroutine */ +s32 sgi_window_init_default(struct sgi_window *object) +{ + struct sgi_widget *p; + SDL_Rect rect; + SDL_Surface *surface; + + /* 是否已经初始过 */ + if (object->initialized) { + return 0; + } + + /* 申请主背景资源 */ + surface = request_image(object->image.name, object->image.flags); + if (!surface) { + return FAIL; + } + + /* 申请widget资源(如果有) */ + p = object->widget; + if (p) { + object->image.image = clone_surface(surface); + + /* 释放原来的主背景资源 */ + release_image(surface); + + if (!object->image.image) { + printf("clone surface fail.\n"); + return FAIL; + } + object->reallocated = 1; + } + else { + object->image.image = surface; + } + + /* 组合widget */ + while (p) { + if (!p->image.name) { + break; + } + + p->image.image = request_image(p->image.name, p->image.flags); + if (p->image.image) { + rect.x = p->x; + rect.y = p->y; + rect.w = p->w; + rect.h = p->h; + SDL_BlitSurface(p->image.image, NULL, + object->image.image, &rect); + release_image(p->image.image); + p->image.image = NULL; + } + p++; + } + + /* 置初始标志 */ + object->initialized = 1; + + return 0; +} + +void sgi_window_deinit_default(struct sgi_window *object) +{ + /* 释放资源 */ + if (object->reallocated) { + release_clone_surface(object->image.image); + object->reallocated = 0; + } + else { + release_image(object->image.image); + } + object->image.image = NULL; + + /* 重置初始标志 */ + object->initialized = 0; +} + +s32 sgi_window_frame_default(struct sgi_window *object) +{ + return 0; +} + +void sgi_window_render_default(struct sgi_window *object, SDL_Surface *screen) +{ + SDL_Rect rect; + + if (!(object->parent->redraw || object->redraw)) { + return; + } + + rect.x = object->x; + rect.y = object->y; + rect.w = object->w; + rect.h = object->h; + SDL_BlitSurface(object->image.image, NULL, screen, &rect); + + /* 提交重绘区域 */ + invalidate_rect(object->parent, object->x, object->y, + object->x + object->w, object->y + object->h); + object->redraw = 0; +} diff --git a/src/sgi_data.cpp b/src/sgi_data.cpp new file mode 100644 index 0000000..70c0b4c --- /dev/null +++ b/src/sgi_data.cpp @@ -0,0 +1,1243 @@ +#include +#include +#include +#include +#include "global_func.h" + +static std::vector s_person_vec; +static std::vector s_gun_vec; +static std::list s_lock_list; +static struct box_data s_gun_box; +static struct unit_data s_unit; +static struct person_data_mem s_person_reg_data; +static struct box_info s_box_info[BOX_NUMS]; +static u32 s_log_no[LOG_MAX] = {0}; + +//struct person_data g_person_modify; +static struct gun_data s_gun_reg_data; +s32 g_data_update_state; + +s32 copy_file(char *out, char *in) +{ + FILE *fi = fopen(in, "rb"); + if (fi == NULL) { + return -1; + } + + FILE *fo = fopen(out, "wb"); + if (fo == NULL) { + fclose(fi); + return -1; + } + + fseek(fi, 0, SEEK_END); + size_t size = ftell(fi); + fseek(fi, 0, SEEK_SET); + + void *buf = malloc(size); + if (buf == NULL) { + fclose(fi); + fclose(fo); + return -1; + } + + fread(buf, 1, size, fi); + fwrite(buf, 1, size, fo); + + free(buf); + + fclose(fi); + fclose(fo); + + return 0; +} + +void *open_w(const char *name, size_t *size) +{ + int fd; + void *ptr; + + /* 打开文件 */ + if ((fd = open(name, O_RDWR)) < 0) { + return NULL; + } + + *size = lseek(fd, 0, SEEK_END); + ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + /* 关闭文件 */ + close(fd); + + return ptr; +} + +s32 data_flush(void *ptr, size_t size) +{ + return msync(ptr, size, MS_SYNC); +} + +void close_w(void *ptr, size_t size) +{ + if (ptr) { + munmap(ptr, size); + } +} + +void *open_r(const char *name, size_t *size) +{ + int fd; + void *ptr; + + /* 打开文件 */ + if ((fd = open(name, O_RDONLY)) < 0) { + return NULL; + } + + *size = lseek(fd, 0, SEEK_END); + ptr = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0); + + /* 关闭文件 */ + close(fd); + + return ptr; +} + +void close_r(void *ptr, size_t size) +{ + if (ptr) { + munmap(ptr, size); + } +} + +static s32 open_person_db(char *dbname, s32 spec) +{ + u32 i; + u32 count; + struct person_data_mem person; + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 获取记录数 */ + fseek(fp, 0, SEEK_END); + count = ftell(fp) / sizeof(struct person_data); + fseek(fp, 0, SEEK_SET); + + /* 限定最大用户数不能超过65536 */ + count &= 0xffff; + + /* 读取人员数据 */ + for (i = 0; i < count; ++i) { + fread(&person, 1, sizeof(struct person_data), fp); + if (spec) { + person.index = (1 << 30) | i; /* super user flag */ + } + else { + person.index = i; + } + s_person_vec.push_back(person); + } + + /* 关闭数据文件 */ + fclose(fp); + + return count; +} + +static s32 load_gun_data(const char *dbname) +{ + u32 i; + u32 count; + struct gun_data gun; + FILE *fp; + + /* 清空枪支记录数据 */ + s_gun_vec.clear(); + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 获取记录数 */ + fseek(fp, 0, SEEK_END); + count = ftell(fp) / sizeof(struct gun_data); + fseek(fp, 0, SEEK_SET); + + /* 读取人员数据 */ + for (i = 0; i < count; ++i) { + fread(&gun, 1, sizeof(struct gun_data), fp); + s_gun_vec.push_back(gun); + } + + /* 关闭数据文件 */ + fclose(fp); + + return count; +} + +static s32 open_gun_box_db(const char *dbname) +{ + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 读取数据 */ + fread(&s_gun_box, 1, sizeof(struct box_data), fp); + + /* 关闭数据文件 */ + fclose(fp); + + return 1; +} + +static s32 open_unit_db(const char *dbname) +{ + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 读取数据 */ + fread(&s_unit, 1, sizeof(struct unit_data), fp); + + /* 关闭数据文件 */ + fclose(fp); + + return 1; +} + +static void borrow_update_box_info(u32 *cells) +{ + /* box max cap 128 */ + u32 i,j; + s32 index = 0; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + if ((cells[i] & (1 << j)) != 0) { + s_box_info[index].state |= 2; + } + + if (++index >= BOX_NUMS) { + break; + } + } + } +} + +static void return_update_box_info(u32 *cells) +{ + /* box max cap 128 */ + u32 i,j; + s32 index = 0; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + if ((cells[i] & (1 << j)) != 0) { + s_box_info[index].state &= ~2; + } + + if (++index >= BOX_NUMS) { + break; + } + } + } +} + +#if 0 +static void update_box_info(u32 *cells) +{ + /* box max cap 128 */ + u32 i,j; + s32 index = 0; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + if ((cells[i] & (1 << j)) != 0) { + s_box_info[index].state |= 2; + } + else { + s_box_info[index].state &= ~2; + } + index++; + } + } +} +#endif + +void load_gun_box_info(void) +{ + u32 i; + u32 size; + + memset(&s_box_info, 0, sizeof(s_box_info)); + + /* 用枪支登记信息初始枪柜 */ + //printf("gun vector size: %d\n", s_gun_vec.size()); + for (i = 0; i < s_gun_vec.size(); ++i) { + if (s_gun_vec[i].lock_code < 1 + || s_gun_vec[i].lock_code > BOX_NUMS) { + continue; + } + + //printf("gun vector lock code: %d\n", s_gun_vec[i].lock_code); + s_box_info[s_gun_vec[i].lock_code - 1].state = 1; + sgi_ncp16(s_box_info[s_gun_vec[i].lock_code].gun_code, + s_gun_vec[i].code, + COUNTOF(s_box_info[s_gun_vec[i].lock_code].gun_code)); + sgi_ncp16(s_box_info[s_gun_vec[i].lock_code].gun_model, + s_gun_vec[i].model, + COUNTOF(s_box_info[s_gun_vec[i].lock_code].gun_model)); + sgi_ncp16(s_box_info[s_gun_vec[i].lock_code].holder, + s_gun_vec[i].holder, + COUNTOF(s_box_info[s_gun_vec[i].lock_code].holder)); + } + + /* 用枪支借出信息初始枪柜 */ + struct borrow_ctrl *pcont; + struct borrow_ctrl *p; + pcont = (struct borrow_ctrl *)open_r(DBR(borrow), &size); + if (pcont == NULL) { + return; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + borrow_update_box_info(p->cells); + p++; + } + + for (i = 0; i < BOX_NUMS; ++i) { + printf("box-info[%d]: %d\n", i, s_box_info[i].state); + + } + + /* 关闭 */ + close_r(pcont, size); +} + +static void load_log_no(void) +{ + size_t size; + void *p; + + /* manager log no. */ + p = open_r(DBL(manager), &size); + if (p) { + struct log_manager *m = (struct log_manager *)((u8 *)p + size + - sizeof(struct log_manager)); + s_log_no[LOG_MANAGER] = m->id & 0xffff; + close_r(p, size); + } + + /* */ + p = open_r(DBL(borrow), &size); + if (p) { + struct log_borrow *b = (struct log_borrow *)((u8 *)p + size + - sizeof(struct log_borrow)); + s_log_no[LOG_BORROW] = b->id & 0xffff; + close_r(p, size); + } + + /* */ + p = open_r(DBL(back), &size); + if (p) { + struct log_borrow *r = (struct log_borrow *)((u8 *)p + size + - sizeof(struct log_borrow)); + s_log_no[LOG_RETURN] = r->id & 0xffff; + close_r(p, size); + } + + /* */ + p = open_r(DBL(alarm), &size); + if (p) { + struct log_alarm *a = (struct log_alarm *)((u8 *)p + size + - sizeof(struct log_alarm)); + s_log_no[LOG_ALARM] = a->id & 0xffff; + close_r(p, size); + } + + /* */ + p = open_r(DBL(syslog), &size); + if (p) { + struct log_system *s = (struct log_system *)((u8 *)p + size + - sizeof(struct log_system)); + s_log_no[LOG_SYSTEM] = s->id & 0xffff; + close_r(p, size); + } +} + +s32 load_person_data(void) +{ + u32 count = 0; + + /* 清空人员记录数据 */ + s_person_vec.clear(); + + /* 加载特殊权限人员数据 */ + count += open_person_db(DBD(super), 1); + + /* 加载普通人员数据 */ + count += open_person_db(DBD(person), 0); + + return count; +} + +s32 data_open(void) +{ + u32 count = 0; + + /* 清空人员记录数据 */ + //s_person_vec.clear(); + s_lock_list.clear(); + + /* 清空枪支记录数据 */ + //s_gun_vec.clear(); + + /* 清空枪柜记录 */ + memset(&s_gun_box, 0, sizeof(struct box_data)); + + /* 清空单位信息 */ + memset(&s_unit, 0, sizeof(struct unit_data)); + + /* 加载特殊权限人员数据 */ + //count += open_person_db(DBD(super), 1); + + /* 加载普通人员数据 */ + //count += open_person_db(DBD(person), 0); + count = load_person_data(); + + /* 加载枪支信息 */ + load_gun_data(DBD(gun)); + + /* 加载枪柜信息 */ + open_gun_box_db(DBD(gun_box)); + + /* 加载单位信息 */ + open_unit_db(DBD(unit)); + + /* 加载枪柜与枪支影射信息 */ + load_gun_box_info(); + + /* 加载日志编号 */ + load_log_no(); + + return count > 0 ? 0 : -1; +} + +void data_close(void) +{ + s_person_vec.clear(); + s_gun_vec.clear(); +} + +s32 search_uid(struct passport_data *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_USER + && (s_person_vec[i].person.fpr1 == param || + s_person_vec[i].person.fpr2 == param)) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->dept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + sgi_ncp16(pass->post, s_person_vec[i].person.post, + COUNTOF(s_person_vec[i].person.post)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_USER + && s_person_vec[i].person.idcard == param) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->dept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + sgi_ncp16(pass->post, s_person_vec[i].person.post, + COUNTOF(s_person_vec[i].person.post)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 search_mid(struct passport_data *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_MANAGER + && (s_person_vec[i].person.fpr1 == param || + s_person_vec[i].person.fpr2 == param)) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->mdept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_MANAGER + && s_person_vec[i].person.idcard == param) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->mdept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 verify_user_pwd(struct passport_data *pass, u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].person.level != LV_USER + || (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->post, s_person_vec[i].person.post, + COUNTOF(s_person_vec[i].person.post)); + } + r = i; + } + + break; + } + + return r; +} + +s32 verify_manager_pwd(struct passport_data *pass, u16 *mid, u16 *pwd) +{ + assert(mid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].person.level != LV_MANAGER + || (sgi_ncmp16(s_person_vec[i].person.uid, mid, + COUNTOF(s_person_vec[i].person.uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + } + r = i; + } + + break; + } + + return r; +} + +static s32 verify_all_user_pwd(u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) != 0) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + r = i; + } + + break; + } + + return r; +} + +static s32 search_all_user(u16 *uid) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) == 0) { + r = i; + break; + } + } + + return r; +} + +static s32 sync_pwd(struct person_data_mem *person, u16 *new_pwd) +{ + s32 r = FAIL; + u32 index; + size_t size; + struct person_data *ptr = NULL; + + /* 打开数据文件 */ + if (person->index & (1 << 30)) { /* super user */ + ptr = (struct person_data *)open_w(DBD(super), &size); + } + else { + ptr = (struct person_data *)open_w(DBD(person), &size); + } + + if (ptr == NULL) { + goto err; + } + + /* 修改内容 */ + index = person->index & 0xffff; + if (index > size / sizeof(struct person_data)) { + goto err; + } + sgi_ncp16(ptr[index].pwd, new_pwd, COUNTOF(ptr[index].pwd)); + + /* 更新到文件 */ + if (msync(ptr, size, MS_SYNC) != 0) { + goto err; + } + + r = 0; + +err: + /* 关闭文件 */ + close_w(ptr, size); + + return r; +} + +s32 change_pwd(u16 *uid, u16 *old_pwd, u16 *new_pwd) +{ + assert(uid != NULL || old_pwd != NULL || new_pwd != NULL); + + s32 r; + + /* 校验旧密码是否有效 */ + r = verify_all_user_pwd(uid, old_pwd); + if (r < 0) { + return r; + } + + /* 修改为新密码 */ + if (sync_pwd(&s_person_vec[r], new_pwd) != 0) { + return FAIL; + } + + sgi_ncp16(s_person_vec[r].person.pwd, new_pwd, + COUNTOF(s_person_vec[r].person.pwd)); + + return 0; +} + +static s32 sgi_append_data(const char *name, void *data, size_t size) +{ + FILE *fp; + + /* 打开日志文件 */ + if (access(name, R_OK | W_OK) == 0) { + fp = fopen(name, "ab"); + } + else { + fp = fopen(name, "wb"); + } + if (fp == NULL) { + printf("sgi_append_data open fail\n"); + return FAIL; + } + + /* 追加数据 */ + if (fwrite(data, 1, size, fp) < size) { + fclose(fp); + printf("sgi_append_data write fail\n"); + return FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + return 0; +} + +s32 register_person(struct person_data_mem *person) +{ + u32 i; + s32 index = 0; + + if (search_all_user(person->person.uid) != ID_INVALID) { + /* user exist */ + return ID_EXIST; + } + + if (sgi_append_data(DBD(person), person, + sizeof(struct person_data)) != 0) { + return APPEND_FAIL; + } + + /* 追加到列表 */ + for (i = 0; i < s_person_vec.size(); ++i) { + if ((s_person_vec[i].index & (1 << 30)) == 0) { /* normal user */ + index++; + } + } + person->index = index; + s_person_vec.push_back(*person); + + return SUCCESS; +} + +s32 delete_person(struct person_data_mem *data) +{ + u32 i; + + FILE *fp = fopen(DBT(person-tmp), "wb"); + if (fp == NULL) { + return -1; + } + + for (i = 0; i < s_person_vec.size(); ++i) { + if ((s_person_vec[i].index & (1 << 30)) != 0) { /* super user */ + continue; + } + + if (sgi_ncmp16(data->person.uid, s_person_vec[i].person.uid, + COUNTOF(data->person.uid)) == 0) { + continue; + } + + fwrite(&s_person_vec[i].person, 1, sizeof(struct person_data), fp); + } + + fclose(fp); + + if (copy_file(DBD(person-bak), DBD(person)) != 0) { + return -1; + } + + if (copy_file(DBD(person), DBT(person-tmp)) != 0) { + copy_file(DBD(person), DBD(person-bak)); + return -1; + } + + /* */ + load_person_data(); + + return 0; +} + +s32 update_person(struct person_data_mem *data) +{ + u32 i; + u32 size; + s32 found = 0; + s32 result = APPEND_FAIL; + struct person_data *p,*pcont; + const char *dbname = DBD(person); + + pcont = (struct person_data *)open_w(dbname, &size); + if (pcont == NULL) { + goto end; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct person_data); ++i) { + if (sgi_ncmp16(p->uid, data->person.uid, COUNTOF(p->uid)) == 0) { + found = 1; + break; + } + p++; + } + + if (found) { + memcpy(p, data, sizeof(struct person_data)); + + /* 更新到文件 */ + if (msync(pcont, size, MS_SYNC) != 0) { + goto end; + } + + /* */ + load_person_data(); + + result = 0; + } + +end: + if (pcont) { + close_w(pcont, size); + } + + return result; +} + +static s32 search_gun(u16 *code) +{ + assert(code != NULL); + + u32 i; + s32 r = CODE_INVALID; + + for (i = 0; i < s_gun_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_gun_vec[i].code, code, + COUNTOF(s_gun_vec[i].code)) == 0) { + r = i; + break; + } + } + + return r; +} + +s32 register_gun(struct gun_data *gun) +{ + if (search_gun(gun->code) != CODE_INVALID) { /* gun exist */ + return ID_EXIST; + } + + if (sgi_append_data(DBD(gun), gun, + sizeof(struct gun_data)) != 0) { + return APPEND_FAIL; + } + + /* 追加到列表 */ + s_gun_vec.push_back(*gun); + + /* 更新槍柜影射信息 */ + load_gun_box_info(); + + return SUCCESS; +} + +s32 update_gun(struct gun_data *data) +{ + u32 i; + u32 size; + s32 found = 0; + s32 result = APPEND_FAIL; + struct gun_data *p,*pcont; + const char *dbname = DBD(gun); + + pcont = (struct gun_data *)open_w(dbname, &size); + if (pcont == NULL) { + goto end; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct gun_data); ++i) { + if (sgi_ncmp16(p->code, data->code, COUNTOF(p->code)) == 0) { + found = 1; + break; + } + p++; + } + + if (found) { + memcpy(p, data, sizeof(struct gun_data)); + + /* 更新到文件 */ + if (msync(pcont, size, MS_SYNC) != 0) { + goto end; + } + + /* 重新加载到内存影射表 */ + load_gun_data(DBD(gun)); + + /* 更新槍柜影射信息 */ + load_gun_box_info(); + + result = 0; + } + +end: + if (pcont) { + close_w(pcont, size); + } + + return result; +} + +s32 delete_gun(struct gun_data *data) +{ + u32 i; + + FILE *fp = fopen(DBT(gun-tmp), "wb"); + if (fp == NULL) { + return -1; + } + + for (i = 0; i < s_gun_vec.size(); ++i) { + if (sgi_ncmp16(data->code, s_gun_vec[i].code, + COUNTOF(data->code)) == 0) { + continue; + } + + fwrite(&s_gun_vec[i], 1, sizeof(struct gun_data), fp); + } + + fclose(fp); + + if (copy_file(DBD(gun-bak), DBD(gun)) != 0) { + return -1; + } + + if (copy_file(DBD(gun), DBT(gun-tmp)) != 0) { + copy_file(DBD(gun), DBD(gun-bak)); + return -1; + } + + /* 重新加载到内存影射表 */ + load_gun_data(DBD(gun)); + + /* 更新槍柜影射信息 */ + load_gun_box_info(); + + return 0; + +} + +s32 register_box(struct box_data *box) +{ + FILE *fp; + const char *name = DBD(gun_box); + + /* 打开文件 */ + fp = fopen(name, "wb"); + if (fp == NULL) { + return FAIL; + } + + /* 写入数据 */ + if (fwrite(box, 1, sizeof(struct box_data), fp) < sizeof(struct box_data)) { + fclose(fp); + return FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + /* */ + memcpy(&s_gun_box, box, sizeof(struct box_data)); + + return 0; +} + +s32 register_unit(struct unit_data *unit) +{ + FILE *fp; + const char *name = DBD(unit); + + /* 打开文件 */ + fp = fopen(name, "wb"); + if (fp == NULL) { + return REGISTER_FAIL; + } + + /* 写入数据 */ + if (fwrite(unit, 1, sizeof(struct unit_data), fp) < sizeof(struct unit_data)) { + fclose(fp); + return REGISTER_FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + /* */ + memcpy(&s_unit, unit, sizeof(struct unit_data)); + + return SUCCESS; +} + +struct box_info *get_box_info(void) +{ + return s_box_info; +} + +u16 *get_box_code(void) +{ + return s_gun_box.code; +} + +struct unit_data *get_unit_info(void) +{ + return &s_unit; +} + +s32 enroll_borrow(struct passport_data *pass, u32 *cells) +{ + ///* 4 x sizeof(u32) x 8 = 128 bit = box-cap */ + struct borrow_ctrl content; + const char *dbname = DBR(borrow); + + memset(&content, 0, sizeof(struct borrow_ctrl)); + sgi_cp16(content.uid, pass->uid); + content.borrow_time = pass->borrow_time; + content.return_time = pass->return_time; + memcpy(content.cells, cells, sizeof(content.cells)); + + if (sgi_append_log(dbname, &content, sizeof(struct borrow_ctrl)) != 0) { + return ENROLL_FAIL; + } + + /* 更新枪柜实时记录 */ + borrow_update_box_info(cells); + + /* 更新借还枪超时监控 */ + borrow_vector_add(pass); + + return 0; +} + +s32 search_borrow_info(struct passport_data *pass) +{ + u32 i; + u32 size; + s32 found = 0; + struct borrow_ctrl *p,*pcont; + const char *dbname = DBR(borrow); + + pcont = (struct borrow_ctrl *)open_w(dbname, &size); + if (pcont == NULL) { + goto end; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + if (sgi_ncmp16(p->uid, pass->uid, COUNTOF(p->uid)) == 0) { + if (p->cells[0] != 0 || p->cells[1] != 0 + || p->cells[2] != 0 || p->cells[3] != 0) { + found = 1; + break; + } + } + p++; + } + +end: + if (pcont) { + close_w(pcont, size); + } + + return found; +} + +s32 enroll_return(struct passport_data *pass, u32 *cells) +{ + ///* 4 x sizeof(u32) x 8 = 128 bit = box-cap */ + u32 i; + u32 size; + s32 r = FAIL; + struct borrow_ctrl *p,*pcont; + const char *dbname = DBR(borrow); + + pcont = (struct borrow_ctrl *)open_w(dbname, &size); + if (pcont == NULL) { + goto err; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + if (sgi_ncmp16(p->uid, pass->uid, COUNTOF(p->uid)) == 0) { + p->cells[0] &= ~cells[0]; + p->cells[1] &= ~cells[1]; + p->cells[2] &= ~cells[2]; + p->cells[3] &= ~cells[3]; + } + p++; + } + + /* 更新到文件 */ + if (msync(pcont, size, MS_SYNC) != 0) { + goto err; + } + + /* 更新枪柜实时记录 */ + return_update_box_info(cells); + + /* 更新借还枪超时监控 */ + borrow_vector_remove(pass, pcont, size / sizeof(struct borrow_ctrl)); + + r = 0; +err: + if (pcont) { + close_w(pcont, size); + } + + return r; +} + +struct person_data *get_person_reg_data(void) +{ + return (struct person_data *)&s_person_reg_data; +} + +struct gun_data *get_gun_reg_data(void) +{ + return (struct gun_data *)&s_gun_reg_data; +} + +void person_reg_data_clear(void) +{ + memset(&s_person_reg_data, 0, sizeof(struct person_data_mem)); +} + +u32 get_log_no(enum sgi_log_type type) +{ + return (++s_log_no[type] & 0xffff); +} + +u8 *get_return_info(u16 *uid) +{ + static u8 info[BOX_NUMS]; + u32 i,j,k; + u32 size; + + /* */ + memset(info, 0, sizeof(info)); + + /* */ + struct borrow_ctrl *pcont; + struct borrow_ctrl *p; + pcont = (struct borrow_ctrl *)open_r(DBR(borrow), &size); + if (pcont == NULL) { + return info; + } + + p = pcont; + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i,p++) { + if (sgi_ncmp16(uid, p->uid, COUNTOF(p->uid)) != 0) { + continue; + } + + s32 exit = 0; + for (j = 0; j < 4; ++j) { + for (k = 0; k < 32; ++k) { + if (j * 32 + k > BOX_NUMS) { + exit = 1; + break; + } + + if ((p->cells[j] & (1 << k)) != 0) { + info[j * 32 + k] |= 1; + } + } + + if (exit) { + break; + } + } + } + + /* 关闭 */ + close_r(pcont, size); + + return info; +} + +s32 get_lock_list(void) +{ + s32 addr; + + if (s_lock_list.empty()) { + return -1; + } + + addr = s_lock_list.front(); + s_lock_list.pop_front(); + + return addr; +} + +void set_lock_list(s32 addr) +{ + s_lock_list.push_back(addr); +} diff --git a/src/sgi_data.h b/src/sgi_data.h new file mode 100644 index 0000000..d5f4f87 --- /dev/null +++ b/src/sgi_data.h @@ -0,0 +1,113 @@ +#ifndef SGI_DATA_H +#define SGI_DATA_H + +#include +#include "sgi_types.h" + +struct person_data { + u16 uid[16]; + u16 name[16]; + u16 sex[2]; + u32 age; + u16 dept[16]; + u16 post[16]; + u16 gun[16]; + u16 gun_code[16]; + u16 lock_code; + u16 level; + u16 fpr1; + u16 fpr2; + u32 idcard; + u16 pwd[16]; + u16 phone[16]; +}; + +struct person_data_mem { + struct person_data person; + s32 index; +}; + +struct gun_data { + u16 code[16]; + u16 model[16]; + u16 caliber[8]; + u16 bullet[8]; + u16 holder[16]; + u16 unit[16]; + u16 stock_date[16]; + u16 lock_code; + u16 status; +}; + +struct sgi_bullet { + u16 name[16]; + u16 model[16]; + u16 for_gun[16]; + u16 amount; + u16 lock_code; + u16 batch[16]; + u16 unit[16]; +}; + +struct box_data { + u16 type; + u16 cap; + u16 code[16]; + u16 model[16]; + u16 manager[16]; + u16 unit[16]; +}; + +struct unit_data { + u16 name[16]; + u16 addr[32]; + u16 dept[16]; + u16 parent[16]; +}; + +struct passport_data { + u32 visit; + u16 uid[16]; + u16 name[16]; + u16 dept[16]; + u16 post[16]; + u16 mid[16]; + u16 mname[16]; + u16 mdept[16]; + char photo[64]; + time_t borrow_time; + time_t return_time; + s16 fpr_enroll; + s16 fpr_id; + s32 reg_flag; +}; + +struct borrow_ctrl { + u16 uid[16]; + time_t borrow_time; + time_t return_time; + u32 cells[4]; +}; + +struct box_info { + s32 state; + u16 gun_code[16]; + u16 gun_model[16]; + u16 holder[16]; +}; + +#if 0 +struct alarm_data { + s16 type; + u16 lock_addr; + time_t time; + u16 content[32]; +}; +#endif +struct alarm_data { + u16 cabinet_id[16]; + time_t time; + u16 content[32]; +}; + +#endif diff --git a/src/sgi_form_manage.cpp b/src/sgi_form_manage.cpp new file mode 100644 index 0000000..5afeaa3 --- /dev/null +++ b/src/sgi_form_manage.cpp @@ -0,0 +1,166 @@ +#include "global_func.h" + +static s32 s_app_quit = 0; +static struct sgi_form *s_active_form = NULL; +static struct sgi_form *s_old_form = NULL; +static struct sgi_form *s_next_form = NULL; + +static struct sgi_form_list s_form_list[] = { + FORM_LIST_FILL_ALL +}; + +s32 app_loop(SDL_Surface *screen) +{ + SDL_Event event; + struct sgi_msg msg; + + s_active_form->msg.clear(); + + while (!s_app_quit) { + + assert(s_active_form != NULL); + + /* monitor */ + monitor(); + + /* network realtime monitor */ + net_monitor(); + + if (SDL_PollEvent(&event)) { + /* message push */ + if (event.type == SDL_MOUSEBUTTONDOWN) { +#if 0 + if (event.button.x > 700 && + event.button.y < 80) { + printf("app quit.\n"); + s_app_quit = 1; + continue; + } +#endif + msg.type = SGI_MOUSEDOWN; + msg.wparam = 0; + msg.lparam = (event.button.y << 16) | (event.button.x & 0xffff); + s_active_form->msg.push_back(msg); + } + else if (event.type == SDL_MOUSEBUTTONUP) { + msg.type = SGI_MOUSEUP; + msg.wparam = 0; + msg.lparam = (event.button.y << 16) | (event.button.x & 0xffff); + s_active_form->msg.push_back(msg); + } + } + + /* 置消息列表头标志 */ + if (!s_active_form->msg.empty()) { + struct sgi_msg &t = s_active_form->msg.front(); + t.wparam |= 0x8000; + } + + /* 进行消息循环 */ + s_active_form->frame(s_active_form); + s_active_form->render(s_active_form, screen); + + /* 移除已处理的消息 */ + if (!s_active_form->msg.empty()) { + struct sgi_msg &t = s_active_form->msg.front(); + if ((t.wparam & 0x8000) == 0x8000) { + s_active_form->msg.pop_front(); + } + } + + /* 是否需要进行form切换 */ + if (s_next_form != NULL) { + /* 执行前页面的退出动作 */ + if (s_active_form->exit) { + s_active_form->exit(s_active_form); + } + s_active_form->msgbox = NULL; + + /* 清除前页面消息队列 */ + s_active_form->msg.clear(); + + /* 切换form */ + s_old_form = s_active_form; + s_active_form = s_next_form; + s_active_form->redraw = 1; + s_next_form = NULL; + + /* 如果form未初始,先执行初始化 */ + if (!s_active_form->initialized) { + printf("active form init.\n"); + if (s_active_form->init(s_active_form) != 0) { + printf("form init fail: %s\n", s_active_form->name); + return FAIL; + } + } + + /* 执行新页面的初始动作 */ + if (s_active_form->enter) { + s_active_form->enter(s_active_form); + } + s_active_form->msgbox = NULL; + } + + /* 如果队列中有消息,立即处理 */ + if (!s_active_form->msg.empty()) { + continue; + } + + SDL_Delay(10); + } + + /* 清除form资源 */ + u32 i; + for (i = 0; i < sizeof(s_form_list) / sizeof(struct sgi_form_list); ++i) { + if (s_form_list[i].created) { + s_form_list[i].destroy(); + s_form_list[i].created = 0; + printf("destroy form: %s\n", s_form_list[i].form->name); + } + } + + return 0; +} + +void sgi_form_show(struct sgi_form *form) +{ + u32 i; + + assert(form != NULL); + + /* 检查form是否已经创建 */ + for (i = 0; i < sizeof(s_form_list) / sizeof(struct sgi_form_list); ++i) { + if (form == s_form_list[i].form) { + if (!s_form_list[i].created) { + s_form_list[i].create(); + s_form_list[i].created = 1; + } + break; + } + } + + if (s_active_form == NULL) { + /* 页面切换 */ + s_active_form = form; + + /* 如果form未初始,先执行初始化 */ + if (!s_active_form->initialized) { + printf("active form init.\n"); + if (s_active_form->init(s_active_form) != 0) { + printf("form init fail: %s\n", s_active_form->name); + return; + } + } + + /* 执行新页面的进入动作 */ + if (s_active_form->enter) { + s_active_form->enter(s_active_form); + } + } + else { + s_next_form = form; + } + + printf("form name: %s\n", s_active_form->name); +} + diff --git a/src/sgi_ime.cpp b/src/sgi_ime.cpp new file mode 100644 index 0000000..7afa721 --- /dev/null +++ b/src/sgi_ime.cpp @@ -0,0 +1,156 @@ +#include "global_func.h" + +static struct sgi_key s_ime_key[KEY_NUMS] = { + IME_KEY(0,42,62,44),IME_KEY(61,42,62,44),IME_KEY(122,42,62,44), + IME_KEY(183,42,62,44),IME_KEY(244,42,62,44),IME_KEY(304,42,62,44), + IME_KEY(365,42,62,44),IME_KEY(426,42,62,44),IME_KEY(486,42,62,44), + IME_KEY(547,42,62,44),IME_KEY(608,42,84,44), + + IME_KEY(40,85,62,44),IME_KEY(102,85,62,44),IME_KEY(164,85,62,44), + IME_KEY(225,85,62,44),IME_KEY(285,85,62,44),IME_KEY(346,85,62,44), + IME_KEY(407,85,62,44),IME_KEY(468,85,62,44),IME_KEY(529,85,62,44), + IME_KEY(589,85,62,44), + + IME_KEY(73,127,62,44),IME_KEY(133,127,62,44),IME_KEY(194,127,62,44), + IME_KEY(255,127,62,44),IME_KEY(316,127,62,44),IME_KEY(376,127,62,44), + IME_KEY(437,127,62,44),IME_KEY(498,127,62,44),IME_KEY(559,127,62,44), + + IME_KEY(91,170,62,44),IME_KEY(152,170,62,44),IME_KEY(213,170,62,44), + IME_KEY(274,170,62,44),IME_KEY(334,170,62,44),IME_KEY(395,170,62,44), + IME_KEY(456,170,62,44),IME_KEY(517,170,84,44), +}; + +static struct sgi_key s_ime_selector[10] = { + IME_KEY(0,0,84,42),IME_KEY(84,0,99,42),IME_KEY(183,0,61,42), + IME_KEY(244,0,61,42),IME_KEY(305,0,61,42),IME_KEY(366,0,61,42), + IME_KEY(426,0,61,42),IME_KEY(487,0,61,42),IME_KEY(548,0,61,42), + IME_KEY(608,0,84,42), +}; + +static const struct sgi_ime_caption s_ime_caption[3] = { + {{ + {(u16)L'1'},{(u16)L'2'},{(u16)L'3'},{(u16)L'4'},{(u16)L'5'}, + {(u16)L'6'},{(u16)L'7'},{(u16)L'8'},{(u16)L'9'},{(u16)L'0'}, + {(u16)L'删',(u16)L'除'}, + + {(u16)L'Q'},{(u16)L'W'},{(u16)L'E'},{(u16)L'R'},{(u16)L'T'}, + {(u16)L'Y'},{(u16)L'U'},{(u16)L'I'},{(u16)L'O'},{(u16)L'P'}, + + {(u16)L'A'},{(u16)L'S'},{(u16)L'D'},{(u16)L'F'},{(u16)L'G'}, + {(u16)L'H'},{(u16)L'J'},{(u16)L'K'},{(u16)L'L'}, + + {(u16)L'Z'},{(u16)L'X'},{(u16)L'C'},{(u16)L'V'},{(u16)L'B'}, + {(u16)L'N'},{(u16)L'M'},{(u16)L'英',(u16)L'文'}, + }}, + + {{ + {(u16)L'~'},{(u16)L'!'},{(u16)L'@'},{(u16)L'#'},{(u16)L'$'}, + {(u16)L'%'},{(u16)L'.'},{(u16)L'&'},{(u16)L'*'},{(u16)L'_'}, + {(u16)L'删',(u16)L'除'}, + + {(u16)L'q'},{(u16)L'w'},{(u16)L'e'},{(u16)L'r'},{(u16)L't'}, + {(u16)L'y'},{(u16)L'u'},{(u16)L'i'},{(u16)L'o'},{(u16)L'p'}, + + {(u16)L'a'},{(u16)L's'},{(u16)L'd'},{(u16)L'f'},{(u16)L'g'}, + {(u16)L'h'},{(u16)L'j'},{(u16)L'k'},{(u16)L'l'}, + + {(u16)L'z'},{(u16)L'x'},{(u16)L'c'},{(u16)L'v'},{(u16)L'b'}, + {(u16)L'n'},{(u16)L'm'},{(u16)L'符',(u16)L'号'}, + }}, + + {{ + {(u16)L'1'},{(u16)L'2'},{(u16)L'3'},{(u16)L'4'},{(u16)L'5'}, + {(u16)L'6'},{(u16)L'7'},{(u16)L'8'},{(u16)L'9'},{(u16)L'0'}, + {(u16)L'删',(u16)L'除'}, + + {(u16)L'Q'},{(u16)L'W'},{(u16)L'E'},{(u16)L'R'},{(u16)L'T'}, + {(u16)L'Y'},{(u16)L'U'},{(u16)L'I'},{(u16)L'O'},{(u16)L'P'}, + + {(u16)L'A'},{(u16)L'S'},{(u16)L'D'},{(u16)L'F'},{(u16)L'G'}, + {(u16)L'H'},{(u16)L'J'},{(u16)L'K'},{(u16)L'L'}, + + {(u16)L'Z'},{(u16)L'X'},{(u16)L'C'},{(u16)L'V'},{(u16)L'B'}, + {(u16)L'N'},{(u16)L'M'},{(u16)L'拼',(u16)L'音'}, + }}, +}; + +static const struct sgi_ime_word s_ime_word[3] = { + { + (u16)L'1',(u16)L'2',(u16)L'3',(u16)L'4',(u16)L'5', + (u16)L'6',(u16)L'7',(u16)L'8',(u16)L'9',(u16)L'0', + 0x08, + + (u16)L'Q',(u16)L'W',(u16)L'E',(u16)L'R',(u16)L'T', + (u16)L'Y',(u16)L'U',(u16)L'I',(u16)L'O',(u16)L'P', + + (u16)L'A',(u16)L'S',(u16)L'D',(u16)L'F',(u16)L'G', + (u16)L'H',(u16)L'J',(u16)L'K',(u16)L'L', + + (u16)L'Z',(u16)L'X',(u16)L'C',(u16)L'V',(u16)L'B', + (u16)L'N',(u16)L'M',0x1b, + }, + + { + (u16)L'~',(u16)L'!',(u16)L'@',(u16)L'#',(u16)L'$', + (u16)L'%',(u16)L'.',(u16)L'&',(u16)L'*',(u16)L'_', + 0x08, + + (u16)L'q',(u16)L'w',(u16)L'e',(u16)L'r',(u16)L't', + (u16)L'y',(u16)L'u',(u16)L'i',(u16)L'o',(u16)L'p', + + (u16)L'a',(u16)L's',(u16)L'd',(u16)L'f',(u16)L'g', + (u16)L'h',(u16)L'j',(u16)L'k',(u16)L'l', + + (u16)L'z',(u16)L'x',(u16)L'c',(u16)L'v',(u16)L'b', + (u16)L'n',(u16)L'm',0x1b, + }, + + { + (u16)L'1',(u16)L'2',(u16)L'3',(u16)L'4',(u16)L'5', + (u16)L'6',(u16)L'7',(u16)L'8',(u16)L'9',(u16)L'0', + 0x08, + + (u16)L'q',(u16)L'w',(u16)L'e',(u16)L'r',(u16)L't', + (u16)L'y',(u16)L'u',(u16)L'i',(u16)L'o',(u16)L'p', + + (u16)L'a',(u16)L's',(u16)L'd',(u16)L'f',(u16)L'g', + (u16)L'h',(u16)L'j',(u16)L'k',(u16)L'l', + + (u16)L'z',(u16)L'x',(u16)L'c',(u16)L'v',(u16)L'b', + (u16)L'n',(u16)L'm',0x1b, + }, +}; + +struct sgi_ime g_sgi_ime; /* 输入法模块 */ +static s32 g_ime_created = 0; + +void sgi_ime_create(void) +{ + if (g_ime_created) { + return; + } + + memset(&g_sgi_ime, 0, sizeof(g_sgi_ime)); + g_sgi_ime.type = SGI_IME; + + /* 按键坐标绑定 */ + g_sgi_ime.key = s_ime_key; + //memcpy(g_sgi_ime.key, s_ime_key, sizeof(s_ime_key)); + //memcpy(g_sgi_ime.caption, s_ime_caption, sizeof(s_ime_caption)); + g_sgi_ime.caption = s_ime_caption; + g_sgi_ime.word = s_ime_word; + //memcpy(g_sgi_ime.word, s_ime_word, sizeof(s_ime_word)); + g_sgi_ime.selector = s_ime_selector; + + /* 其他属性及功能函数指针赋值 */ + SDL_Color color = {0,0,0,0}; + set_object_pos((union sgi_object *)&g_sgi_ime, 50, 226, 693, 213, 15); + set_object_image((union sgi_object *)&g_sgi_ime, "ime-f.png", + "ime-b.png", NULL, NULL, IMG_OPTIMIZE | IMG_ALPHA); + set_object_font((union sgi_object *)&g_sgi_ime, "jht.ttf", 22, color); + set_object_default_func((union sgi_object *)&g_sgi_ime); + + g_ime_created = 1; +} + + diff --git a/src/sgi_log.cpp b/src/sgi_log.cpp new file mode 100644 index 0000000..dba0a80 --- /dev/null +++ b/src/sgi_log.cpp @@ -0,0 +1,662 @@ +#include +#include +#include +#include +#include "global_func.h" + +static lock_t s_alarm_lock; +static lock_t s_system_lock; +static lock_t s_manager_lock; +static lock_t s_report_lock; +static lock_t s_borrow_lock; + +void *sgi_log_open(const char *name, size_t *size) +{ + int fd; + void *ptr; + + /* 打开文件 */ + if ((fd = open(name, O_RDONLY)) < 0) { + return NULL; + } + + *size = lseek(fd, 0, SEEK_END); + ptr = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0); + + /* 关闭文件 */ + close(fd); + + return ptr; +} + +void sgi_log_close(void *handle, size_t size) +{ + if (handle) { + munmap(handle, size); + } +} + +s32 sgi_append_log(const char *name, void *data, size_t size) +{ + FILE *fp; + + /* 打开日志文件 */ + if (access(name, R_OK | W_OK) == 0) { + fp = fopen(name, "ab"); + } + else { + fp = fopen(name, "wb"); + } + if (fp == NULL) { + return FAIL; + } + + /* 追加数据 */ + if (fwrite(data, 1, size, fp) < size) { + fclose(fp); + return FAIL; + } + + /* 关闭日志文件 */ + fclose(fp); + + return 0; +} + +void record_alarm_log(wchar_t *content) +{ + struct log_alarm log; + + memset(&log, 0, sizeof(log_alarm)); + log.id = get_log_no(LOG_ALARM); + time(&log.time); + sgi_ncpw2u(log.content, content, COUNTOF(log.content)); + + s_alarm_lock.lock(); + sgi_append_log(DBL(alarm), &log, sizeof(struct log_alarm)); + s_alarm_lock.unlock(); + + create_data_packet(CMD_DATA_ALARM, &log, sizeof(struct log_alarm)); +} + +void record_alarm_log(u16 *content) +{ + struct log_alarm log; + + memset(&log, 0, sizeof(log_alarm)); + log.id = get_log_no(LOG_ALARM); + time(&log.time); + sgi_ncp16(log.content, content, COUNTOF(log.content)); + + s_alarm_lock.lock(); + sgi_append_log(DBL(alarm), &log, sizeof(struct log_alarm)); + s_alarm_lock.unlock(); + + create_data_packet(CMD_DATA_ALARM, &log, sizeof(struct log_alarm)); +} + +void record_borrow_log(struct passport_data *pass, struct box_info *info) +{ + struct log_borrow log; + + memset(&log, 0, sizeof(struct log_borrow)); + log.id = get_log_no(LOG_BORROW); + log.time = pass->borrow_time; + sgi_ncp16(log.name, g_passport.name, COUNTOF(log.name)); + sgi_ncp16(log.gun_type, info->gun_model, COUNTOF(log.gun_type)); + sgi_ncp16(log.gun_code, info->gun_code, COUNTOF(log.gun_code)); + + s_borrow_lock.lock(); + sgi_append_log(DBL(borrow), &log, sizeof(struct log_borrow)); + s_borrow_lock.unlock(); + + create_data_packet(CMD_DATA_BORROW, &log, sizeof(struct log_borrow)); +} + +void record_return_log(struct passport_data *pass, struct box_info *info) +{ + struct log_borrow log; + + memset(&log, 0, sizeof(struct log_borrow)); + log.id = get_log_no(LOG_RETURN); + log.time = pass->return_time; + sgi_ncp16(log.name, g_passport.name, COUNTOF(log.name)); + sgi_ncp16(log.gun_type, info->gun_model, COUNTOF(log.gun_type)); + sgi_ncp16(log.gun_code, info->gun_code, COUNTOF(log.gun_code)); + + s_borrow_lock.lock(); + sgi_append_log(DBL(back), &log, sizeof(struct log_borrow)); + s_borrow_lock.unlock(); + + create_data_packet(CMD_DATA_RETURN, &log, sizeof(struct log_borrow)); +} + +void recorcd_borrow_report(struct passport_data *pass, int type, int nums) +{ + struct log_report report; + u16 *code = get_box_code(); + + memset(&report, 0, sizeof(struct log_report)); + report.id = time(NULL); + sgi_ncp16(report.cid, code, COUNTOF(report.cid)); + sgi_ncp16(report.uid, pass->uid, COUNTOF(report.uid)); + sgi_ncp16(report.mid, pass->mid, COUNTOF(report.mid)); + report.time = time(NULL); + report.qzsl = nums; + report.type = type; + + s_report_lock.lock(); + sgi_append_log(DBL(report-borrow), &report, sizeof(struct log_report)); + s_report_lock.unlock(); + + create_data_packet(CMD_DATA_REPORT_BORROW, &report, sizeof(struct log_report)); +} + +void recorcd_return_report(struct passport_data *pass, int type, int nums) +{ + struct log_report report; + u16 *code = get_box_code(); + + memset(&report, 0, sizeof(struct log_report)); + report.id = time(NULL); + sgi_ncp16(report.cid, code, COUNTOF(report.cid)); + sgi_ncp16(report.uid, pass->uid, COUNTOF(report.uid)); + sgi_ncp16(report.mid, pass->mid, COUNTOF(report.mid)); + report.time = time(NULL); + report.qzsl = nums; + report.type = type; + + s_report_lock.lock(); + sgi_append_log(DBL(report-back), &report, sizeof(struct log_report)); + s_report_lock.unlock(); + + create_data_packet(CMD_DATA_REPORT_RETURN, &report, sizeof(struct log_report)); +} + +void record_system_log(u16 *name, wchar_t *content) +{ + /* log */ + struct log_system log; + memset(&log, 0, sizeof(struct log_system)); + log.id = get_log_no(LOG_SYSTEM); + time(&log.time); + sgi_ncp16(log.name, name, COUNTOF(log.name)); + sgi_cpw2u(log.content, content); + + s_system_lock.lock(); + sgi_append_log(DBL(syslog), &log, sizeof(struct log_system)); + s_system_lock.unlock(); + + create_data_packet(CMD_DATA_SYSTEM, &log, sizeof(struct log_system)); +} + +void record_manager_log(u16 *name, wchar_t *content) +{ + struct log_manager manager; + + memset(&manager, 0, sizeof(struct log_manager)); + manager.id = get_log_no(LOG_MANAGER); + time(&manager.time); + sgi_ncp16(manager.name, name, COUNTOF(manager.name)); + sgi_ncpw2u(manager.content, content, COUNTOF(manager.content)); + + s_manager_lock.lock(); + sgi_append_log(DBL(manager), &manager, sizeof(struct log_manager)); + s_manager_lock.unlock(); + + create_data_packet(CMD_DATA_MANAGER, &manager, sizeof(struct log_manager)); +} + +static s32 download_borrow_incre(char *path) +{ + struct log_borrow *pcont; + size_t size; + s32 count = 0; + FILE *fp; + u32 i; + + fp = fopen(path, "wb"); + if (!fp) { + return count; + } + + pcont = (struct log_borrow *)open_w(DBL(borrow), &size); + if (!pcont) { + fclose(fp); + return count; + } + + struct log_borrow *p = pcont; + for (i = 0; i < size / sizeof(struct log_borrow); ++i) { + if (!p->down) { + fwrite(p, 1, sizeof(struct log_borrow), fp); + p->down = 1; + count++; + } + p++; + } + + fclose(fp); + + /* 更新下载指针 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + + return count; +} + +static s32 download_return_incre(char *path) +{ + struct log_borrow *pcont; + size_t size; + s32 count = 0; + FILE *fp; + u32 i; + + fp = fopen(path, "wb"); + if (!fp) { + return count; + } + + pcont = (struct log_borrow *)open_w(DBL(back), &size); + if (!pcont) { + fclose(fp); + return count; + } + + struct log_borrow *p = pcont; + for (i = 0; i < size / sizeof(struct log_borrow); ++i) { + if (!p->down) { + fwrite(p, 1, sizeof(struct log_borrow), fp); + p->down = 1; + count++; + } + p++; + } + + fclose(fp); + + /* 更新下载指针 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + + return count; +} + +static s32 download_alarm_incre(char *path) +{ + struct log_alarm *pcont; + size_t size; + s32 count = 0; + FILE *fp; + u32 i; + + fp = fopen(path, "wb"); + if (!fp) { + return count; + } + + pcont = (struct log_alarm *)open_w(DBL(alarm), &size); + if (!pcont) { + fclose(fp); + return count; + } + + struct log_alarm *p = pcont; + for (i = 0; i < size / sizeof(struct log_alarm); ++i) { + if (!p->down) { + fwrite(p, 1, sizeof(struct log_alarm), fp); + p->down = 1; + count++; + } + p++; + } + + fclose(fp); + + /* 更新下载指针 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + + return count; +} + +static s32 download_system_incre(char *path) +{ + struct log_system *pcont; + size_t size; + s32 count = 0; + FILE *fp; + u32 i; + + fp = fopen(path, "wb"); + if (!fp) { + return count; + } + + pcont = (struct log_system *)open_w(DBL(syslog), &size); + if (!pcont) { + fclose(fp); + return count; + } + + struct log_system *p = pcont; + for (i = 0; i < size / sizeof(struct log_system); ++i) { + if (!p->down) { + fwrite(p, 1, sizeof(struct log_system), fp); + p->down = 1; + count++; + } + p++; + } + + fclose(fp); + + /* 更新下载指针 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + + return count; +} + +static s32 download_manager_incre(char *path) +{ + struct log_manager *pcont; + size_t size; + s32 count = 0; + FILE *fp; + u32 i; + + fp = fopen(path, "wb"); + if (!fp) { + return count; + } + + pcont = (struct log_manager *)open_w(DBL(manager), &size); + if (!pcont) { + fclose(fp); + return count; + } + + struct log_manager *p = pcont; + for (i = 0; i < size / sizeof(struct log_manager); ++i) { + if (!p->down) { + fwrite(p, 1, sizeof(struct log_manager), fp); + p->down = 1; + count++; + } + p++; + } + + fclose(fp); + + /* 更新下载指针 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + + return count; +} + +s32 download_log(s32 flag) +{ + time_t now; + struct tm *tmlocal; + char cmd[260]; + s32 count = 0; + + time(&now); + tmlocal = localtime(&now); + + if (flag) { + /* borrow log */ + sprintf(cmd, "cp -f %s %s/borrow_%04d%02d%02d%02d%02d%02d.log", + DBL(borrow), + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + printf(cmd); + printf("\n"); + system(cmd); + + /* return log */ + sprintf(cmd, "cp -f %s %s/return_%04d%02d%02d%02d%02d%02d.log", + DBL(back), + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + printf(cmd); + printf("\n"); + system(cmd); + + /* alarm log */ + sprintf(cmd, "cp -f %s %s/alarm_%04d%02d%02d%02d%02d%02d.log", + DBL(alarm), + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + printf(cmd); + printf("\n"); + system(cmd); + + /* system log */ + sprintf(cmd, "cp -f %s %s/system_%04d%02d%02d%02d%02d%02d.log", + DBL(syslog), + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + printf(cmd); + printf("\n"); + system(cmd); + + /* manager log */ + sprintf(cmd, "cp -f %s %s/manager_%04d%02d%02d%02d%02d%02d.log", + DBL(manager), + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + printf(cmd); + printf("\n"); + system(cmd); + } + else { + /* borrow log */ + sprintf(cmd, "%s/borrow_%04d%02d%02d%02d%02d%02d.log", + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + count += download_borrow_incre(cmd); + printf(cmd); + printf("\n"); + + /* return log */ + sprintf(cmd, "%s/return_%04d%02d%02d%02d%02d%02d.log", + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + count += download_return_incre(cmd); + printf(cmd); + printf("\n"); + + /* alarm log */ + sprintf(cmd, "%s/alarm_%04d%02d%02d%02d%02d%02d.log", + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + count += download_alarm_incre(cmd); + printf(cmd); + printf("\n"); + + /* system log */ + sprintf(cmd, "%s/system_%04d%02d%02d%02d%02d%02d.log", + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + count += download_system_incre(cmd); + printf(cmd); + printf("\n"); + + /* manager log */ + sprintf(cmd, "%s/manager_%04d%02d%02d%02d%02d%02d.log", + UDISK_DEV, tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min, + tmlocal->tm_sec); + count += download_manager_incre(cmd); + printf(cmd); + printf("\n"); + } + + return count; +} + +void mark_to_alarm_file(u32 id) +{ + u32 i; + size_t size; + struct log_alarm *pcont; + + s_alarm_lock.lock(); + + pcont = (struct log_alarm *)open_w(DBL(alarm), &size); + if (!pcont) { + goto clean; + } + + for (i = 0; i < size / sizeof(struct log_alarm); ++i) { + if (pcont[i].id == id && !pcont[i].up) { + pcont[i].up = 1; + break; + } + } + + /* 更新到文件 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + +clean: + + s_alarm_lock.unlock(); +} + +void mark_to_system_file(u32 id) +{ + u32 i; + size_t size; + struct log_system *pcont; + + s_system_lock.lock(); + + pcont = (struct log_system *)open_w(DBL(syslog), &size); + if (!pcont) { + goto clean; + } + + for (i = 0; i < size / sizeof(struct log_system); ++i) { + if (pcont[i].id == id && !pcont[i].up) { + pcont[i].up = 1; + break; + } + } + + /* 更新到文件 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + +clean: + s_system_lock.unlock(); +} + +void mark_to_manager_file(u32 id) +{ + u32 i; + size_t size; + struct log_manager *pcont; + + s_manager_lock.lock(); + + pcont = (struct log_manager *)open_w(DBL(manager), &size); + if (!pcont) { + goto clean; + } + + for (i = 0; i < size / sizeof(struct log_manager); ++i) { + if (pcont[i].id == id && !pcont[i].up) { + pcont[i].up = 1; + break; + } + } + + /* 更新到文件 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + +clean: + s_manager_lock.unlock(); +} + +void mark_to_report_file(u32 id, s32 type) +{ + u32 i; + struct log_report *pcont; + size_t size; + + s_report_lock.lock(); + + if (type == CMD_DATA_REPORT_BORROW) { + pcont = (struct log_report *)open_w(DBL(report-borrow), &size); + } + else { + pcont = (struct log_report *)open_w(DBL(report-back), &size); + } + + if (!pcont) { + goto clean; + } + + for (i = 0; i < size / sizeof(struct log_report); ++i) { + if (pcont[i].id == id && !pcont[i].up) { + pcont[i].up = 1; + break; + } + } + + /* 更新到文件 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + +clean: + s_report_lock.unlock(); +} + +void mark_to_borrow_file(u32 id, s32 type) +{ + u32 i; + struct log_borrow *pcont; + size_t size; + + s_borrow_lock.lock(); + + if (type == CMD_DATA_BORROW) { + pcont = (struct log_borrow *)open_w(DBL(borrow), &size); + } + else { + pcont = (struct log_borrow *)open_w(DBL(back), &size); + } + + if (!pcont) { + goto clean; + } + + for (i = 0; i < size / sizeof(struct log_borrow); ++i) { + if (pcont[i].id == id && !pcont[i].up) { + pcont[i].up = 1; + break; + } + } + + /* 更新到文件 */ + msync(pcont, size, MS_SYNC); + close_w(pcont, size); + +clean: + s_borrow_lock.unlock(); +} diff --git a/src/sgi_log.h b/src/sgi_log.h new file mode 100644 index 0000000..58713b2 --- /dev/null +++ b/src/sgi_log.h @@ -0,0 +1,74 @@ +#ifndef SGI_LOG_H +#define SGI_LOG_H + +#include +#include "sgi_types.h" + +struct log_borrow { + //char id[8]; + u32 id; + u16 name[8]; + time_t time; + u16 gun_type[8]; + u16 gun_code[8]; + u32 bullets; + s16 up; + s16 down; +}; + +struct log_alarm { + //char id[8]; + u32 id; + time_t time; + u16 content[32]; + s16 up; + s16 down; +}; + +struct log_system { + //char id[8]; + u32 id; + u16 name[8]; + time_t time; + u16 content[16]; + s16 up; + s16 down; +}; + +struct log_manager { + //char id[8]; + u32 id; + time_t time; + u16 name[16]; + u16 content[32]; + s16 up; + s16 down; +}; + +struct log_report { + s32 id; + u16 cid[16]; + u16 uid[16]; + u16 mid[16]; + time_t time; + s32 qzsl; + s32 type; + s32 zdlx; + s32 zdsl; + s32 up; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +void *sgi_log_open(const char *name, size_t *size); +void sgi_log_close(void *handle, size_t size); +s32 sgi_append_log(const char *name, void *data, size_t size); +s32 download_log(s32 flag); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sgi_msgbox.cpp b/src/sgi_msgbox.cpp new file mode 100644 index 0000000..687dc99 --- /dev/null +++ b/src/sgi_msgbox.cpp @@ -0,0 +1,31 @@ +#include "global_func.h" + +struct sgi_msgbox g_sgi_msgbox; /* 对话框模块 */ +static s32 g_msgbox_created = 0; + +void sgi_msgbox_create(void) +{ + if (g_msgbox_created) { + return; + } + + memset(&g_sgi_msgbox, 0, sizeof(g_sgi_msgbox)); + g_sgi_msgbox.type = SGI_MSGBOX; + + /* 其他属性及功能函数指针赋值 */ + SDL_Color color = {0,0,0,0}; + set_object_image((union sgi_object *)&g_sgi_msgbox, "msgbox.png", + NULL, "btn-confirm-u.png", "btn-confirm-d.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* button */ + g_sgi_msgbox.button.x = 213; + g_sgi_msgbox.button.y = 113; + + set_object_font((union sgi_object *)&g_sgi_msgbox, "jht.ttf", 22, color); + set_object_default_func((union sgi_object *)&g_sgi_msgbox); + + g_msgbox_created = 1; +} + + diff --git a/src/sgi_resource.cpp b/src/sgi_resource.cpp new file mode 100755 index 0000000..93d5b69 --- /dev/null +++ b/src/sgi_resource.cpp @@ -0,0 +1,374 @@ +#include +#include +#include +#include +#include +#include "global_func.h" +#include "sgi_resource.h" + +static std::vector s_resource_vec; +static Mix_Chunk *s_effect = NULL; +static Mix_Chunk *s_effect_fpr = NULL; + +const char *get_resource_path(void) +{ + return "/sdcard/resource"; +} + +int initialize_resource(SDL_Surface *screen) +{ + int rc; + + /* 初始化图形模块 */ + rc = IMG_Init(IMG_INIT_PNG); + if ((rc & IMG_INIT_PNG) == 0) { + printf("IMG_Init: %s\n", IMG_GetError()); + goto err; + } + + /* 初始化字体模块 */ + rc = TTF_Init(); + if (rc != 0) { + printf("TTF_Init: %s\n", TTF_GetError()); + goto err; + } + + /* 初始化声音模块 */ + rc = Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 2, 1024); + if (rc != 0) { + printf("Mix_OpenAudio: %s\n", Mix_GetError()); + goto err; + } + + /* 加载按键声 */ + s_effect = request_wav("key.wav"); + s_effect_fpr = request_wav("fpr.wav"); + Mix_AllocateChannels(2); + + /* 初始化资源容器 */ + s_resource_vec.clear(); + + return 0; + +err: + return -1; +} + +void destroy_resource(void) +{ + std::vector::iterator it; + + /* 释放资源容器中元素所分配的内存 */ + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + switch ((*it).type) { + case RC_IMAGE: + printf("destroy image\n"); + SDL_FreeSurface((*it).image.data); + break; + + case RC_FONT: + printf("destroy font\n"); + TTF_CloseFont((*it).font.data); + break; + + case RC_WAV: + printf("destroy wav\n"); + Mix_FreeChunk((*it).wav.data); + break; + + case RC_MP3: + printf("destroy mp3\n"); + Mix_FreeMusic((*it).mp3.data); + break; + + default: + break; + } + } + + /* 释放容器本身所占内存 */ + s_resource_vec.clear(); + + /* 释放图形模块 */ + IMG_Quit(); + + /* 释放字体模块 */ + TTF_Quit(); + + /* 释放声音模块 */ + Mix_CloseAudio() ; + + /* */ + release_wav(s_effect); + release_wav(s_effect_fpr); +} + +TTF_Font *request_font(char *id, int font_size) +{ + union resource_t res; + std::vector::iterator it; + char path[MAX_PATH]; + + if (!id) { + return NULL; + } + + printf("request font: %s\n", id); + /* 在资源容器中查找是否有符合条件的字体 */ + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_FONT + && (strcmp((*it).font.id, id) == 0) + && (*it).font.size == font_size) { + (*it).font.ref++; + return (*it).font.data; + } + } + + /* 容器中无符合条件的字体,创建后添加到容器 */ + memset(&res, 0, sizeof(union resource_t)); + res.type = RC_FONT; + res.font.ref++; + strncpy(res.font.id, id, sizeof(res.font.id)); + res.font.size = font_size; + sprintf(path, "%s/%s", get_resource_path(), id); + res.font.data = TTF_OpenFont(path, font_size); + if (res.font.data != NULL) { + s_resource_vec.push_back(res); + return res.font.data; + } + + return NULL; +} + +void release_font(void *font) +{ + std::vector::iterator it; + + /* 在资源容器中查找被引用的字体 */ + if (font == NULL) { + return; + } + + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_FONT + && (Uint32)(*it).font.data == (Uint32)font) { + (*it).font.ref--; + break; + } + } +} + +static SDL_Surface *create_image(char *id, int flags) +{ + SDL_Surface *temp; + SDL_Surface *optimize; + char path[MAX_PATH]; + + /* 从文件中加载图片到表面 */ + sprintf(path, "%s/%s", get_resource_path(), id); + temp = IMG_Load(path); + if (temp == NULL) { + return NULL; + } + + /* 是否需要对表面进行预处理 */ + if (flags & IMG_OPTIMIZE) { + if ((flags & IMG_ALPHA) == IMG_ALPHA) { + optimize = SDL_DisplayFormatAlpha(temp); + } + else { + optimize = SDL_DisplayFormat(temp); + } + + /* 释放原图 */ + SDL_FreeSurface(temp); + } + else { + optimize = temp; + } + + return optimize; +} + +SDL_Surface *request_image(char *id, int flags) +{ + union resource_t res; + std::vector::iterator it; + + if (!id) { + return NULL; + } + + printf("request image: %s\n", id); + /* 在资源容器中查找是否有符合条件的图片 */ + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_IMAGE + && (strcmp((*it).image.id, id ) == 0) + && (*it).image.flags == flags) { + (*it).image.ref++; + return (*it).image.data; + } + } + + /* 创建图片表面 */ + memset(&res, 0, sizeof(union resource_t)); + res.image.data = create_image(id, flags); + if (res.image.data != NULL) { + res.image.type = RC_IMAGE; + res.image.ref++; + strncpy(res.image.id, id, sizeof(res.image.id)); + res.image.flags = flags; + s_resource_vec.push_back(res); + printf("push_back image: type=%d\n", res.type); + } + + return res.image.data; +} + +void release_image(void *image) +{ + std::vector::iterator it; + + /* 在资源容器中查找被引用的图片表面 */ + if (image == NULL) { + return; + } + + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_IMAGE + && (Uint32)(*it).image.data == (Uint32)image) { + (*it).image.ref--; + break; + } + } +} + +static Mix_Chunk *load_wav_file(char *id) +{ + return Mix_LoadWAV(id); +} + +Mix_Chunk *request_wav(char *id) +{ + union resource_t res; + std::vector::iterator it; + char path[MAX_PATH]; + + if (!id) { + return NULL; + } + + /* 先查找声音资源是否已经加载 */ + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_WAV + && (strcmp((*it).wav.id, id) == 0)) { + (*it).wav.ref++; + return (*it).wav.data; + } + } + + /* 未找到,加载声音资源 */ + memset(&res, 0, sizeof(union resource_t)); + sprintf(path, "%s/%s", get_resource_path(), id); + res.wav.data = load_wav_file(path); + if (res.wav.data != NULL) { + res.type = RC_WAV; + res.wav.ref++; + strncpy(res.wav.id, id, sizeof(res.wav.id)); + s_resource_vec.push_back(res); + printf("push back wav: %s\n", id); + } + + return res.wav.data; +} + +void release_wav(void *wav) +{ + std::vector::iterator it; + + if (wav == NULL) { + return; + } + + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_WAV + && (Uint32)(*it).wav.data == (Uint32)wav) { + (*it).wav.ref--; + break; + } + } +} + +static Mix_Music *load_mp3_file(char *id) +{ + return Mix_LoadMUS(id); +} + +Mix_Music *request_mp3(char *id) +{ + union resource_t res; + std::vector::iterator it; + char path[MAX_PATH]; + + if (!id) { + return NULL; + } + + /* 先查找声音资源是否已经加载 */ + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_MP3 + && (strcmp((*it).mp3.id, id) == 0)) { + (*it).mp3.ref++; + return (*it).mp3.data; + } + } + + /* 未找到,加载声音资源 */ + memset(&res, 0, sizeof(union resource_t)); + sprintf(path, "%s/%s", get_resource_path(), id); + res.mp3.data = load_mp3_file(path); + if (res.mp3.data != NULL) { + res.type = RC_MP3; + res.mp3.ref++; + strncpy(res.mp3.id, id, sizeof(res.mp3.id)); + s_resource_vec.push_back(res); + printf("push back mp3: %s\n", id); + } + + return res.mp3.data; +} + +void release_mp3(void *mp3) +{ + std::vector::iterator it; + + if (mp3 == NULL) { + return; + } + + for (it = s_resource_vec.begin(); it != s_resource_vec.end(); it++) { + if ((*it).type == RC_MP3 + && (Uint32)(*it).mp3.data == (Uint32)mp3) { + (*it).mp3.ref--; + break; + } + } +} + +void play_effect(void) +{ + if (s_effect != NULL) { + if(Mix_PlayChannel(-1, s_effect, 0)==-1) { + printf("Mix_PlayChannel: %s\n",Mix_GetError()); + } + } +} + +void play_effect_fpr(void) +{ + if (s_effect_fpr != NULL) { + if(Mix_PlayChannel(-1, s_effect_fpr, 0)==-1) { + printf("Mix_PlayChannel: %s\n",Mix_GetError()); + } + } +} diff --git a/src/sgi_resource.h b/src/sgi_resource.h new file mode 100755 index 0000000..a915c93 --- /dev/null +++ b/src/sgi_resource.h @@ -0,0 +1,49 @@ +#ifndef RESOURCE_H +#define RESOURCE_H + +#include "global_def.h" + +#define RC_IMAGE 1 +#define RC_FONT 2 +#define RC_WAV 3 +#define RC_MP3 4 + +struct resource_image_t { + int type; + int ref; + char id[32]; + int flags; + SDL_Surface *data; +}; + +struct resource_font_t { + int type; + int ref; + char id[32]; + int size; + TTF_Font *data; +}; + +struct resource_wav_t { + int type; + int ref; + char id[32]; + Mix_Chunk *data; +}; + +struct resource_mp3_t { + int type; + int ref; + char id[32]; + Mix_Music *data; +}; + +union resource_t { + int type; + struct resource_image_t image; + struct resource_font_t font; + struct resource_wav_t wav; + struct resource_mp3_t mp3; +}; + +#endif diff --git a/src/sgi_string.c b/src/sgi_string.c new file mode 100644 index 0000000..fdf8fb7 --- /dev/null +++ b/src/sgi_string.c @@ -0,0 +1,190 @@ +#include +//#include + +#include +//#include +//#include +//#include +#include +#include +//#include "sqlite3.h" +#include "sgi_types.h" + +#define MAX_CHAR 512 + +void sgi_sprintf16(u16 *s, const wchar_t *fmt, ...) +{ + wchar_t temp[MAX_CHAR]; + + va_list va; + va_start(va, fmt); + vswprintf(temp, sizeof(temp), fmt, va); + va_end(va); + + wchar_t *t = temp; + while (*t != L'\0') { + *s++ = (u16)*t++; + } + *s = 0; +} + +size_t sgi_len16(u16 *s) +{ + u16 *e = s; + + while (*e++); + + return (e - s - 1); +} + +u16 *sgi_cp16(u16 *dest, u16 *src) +{ + u16 *ptr = dest; + + while ((*dest++ = *src++)); + *dest = 0; + + return ptr; +} + +u16 *sgi_ncp16(u16 *dest, u16 *src, size_t n) +{ + u16 *ptr = dest; + + while (n-- && (*dest++ = *src++)); + *dest = 0; + + return ptr; +} + +s32 sgi_cmp16(u16 *s1, u16 *s2) +{ + while (*s1 && *s2 && *s1 == *s2) { + s1++; s2++; + } + + return (*s1 | *s2) ? -1 : 0; +} + +s32 sgi_ncmp16(u16 *s1, u16 *s2, size_t n) +{ + while (*s1 && *s2 && *s1 == *s2 && n--) { + s1++; s2++; + } + + return (*s1 | *s2) ? n : 0; +} + +u16 *sgi_cpw2u(u16 *dest, wchar_t *src) +{ + u16 *ptr = dest; + + while ((*dest++ = (u16)*src++)); + + return ptr; +} + +wchar_t *sgi_cpu2w(wchar_t *dest, u16 *src) +{ + wchar_t *ptr = dest; + + while ((*dest++ = (wchar_t)*src++)); + + return ptr; +} + +char *sgi_cpu2a(char *dest, u16 *src) +{ + char *ptr = dest; + + while ((*dest++ = (char)*src++)); + + return ptr; +} + +u16 *sgi_cpa2u(u16 *dest, char *src) +{ + u16 *ptr = dest; + + while ((*dest++ = (u16)*src++)); + + return ptr; +} + +u16 *sgi_ncpw2u(u16 *dest, wchar_t *src, size_t n) +{ + u16 *ptr = dest; + + while (n-- && (*dest++ = (u16)*src++)); + + return ptr; +} + +wchar_t *sgi_ncpu2w(w32 *dest, u16 *src, size_t n) +{ + wchar_t *ptr = dest; + + while (n-- && (*dest++ = (w32)*src++)); + + return ptr; +} + +char *sgi_ncpu2a(char *dest, u16 *src, size_t n) +{ + char *ptr = dest; + + while (n-- && (*dest++ = (char)*src++)); + + return ptr; +} + +u16 *sgi_ncpa2u(u16 *dest, char *src, size_t n) +{ + u16 *ptr = dest; + + while (n-- && (*dest++ = (u16)*src++)); + + return ptr; +} + +u16 *sgi_ncat16(u16 *dest, u16 c, size_t n) +{ + u32 i; + + for (i = 0; i < n; ++i) { + if (dest[i] == 0) { + dest[i] = c; + break; + } + } + + return NULL; +} + +u16 *sgi_rdel16(u16 *dest, size_t n) +{ + s32 i; + + for (i = n; i > 0; i--) { + if (dest[i - 1] != 0) { + dest[i - 1] = 0; + break; + } + } + + return dest; +} + +s32 sgi_isdigit16(u16 text) +{ + return iswdigit(text); +} + +s32 sgi_utol(u16 *text, s32 base) +{ + wchar_t ch[20] = {0}; + + sgi_cpu2w(ch, text); + + return wcstol(ch, NULL, base); +} diff --git a/src/sgi_string.h b/src/sgi_string.h new file mode 100644 index 0000000..246a5f3 --- /dev/null +++ b/src/sgi_string.h @@ -0,0 +1,34 @@ +#ifndef SGI_STRING_H +#define SGI_STRING_H + +#include +#include "sgi_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void sgi_sprintf16(u16 *s, const w32 *fmt, ...); +size_t sgi_len16(u16 *s); +u16* sgi_cp16(u16 *dest, u16 *src); +u16* sgi_ncp16(u16 *dest, u16 *src, size_t n); +s32 sgi_cmp16(u16 *s1, u16 *s2); +s32 sgi_ncmp16(u16 *s1, u16 *s2, size_t n); +u16* sgi_cpw2u(u16 *dest, w32 *src); +w32* sgi_cpu2w(w32 *dest, u16 *src); +char* sgi_cpu2a(char *dest, u16 *src); +u16* sgi_cpa2u(u16 *dest, char *src); +u16* sgi_ncpw2u(u16 *dest, w32 *src, size_t n); +w32* sgi_ncpu2w(w32 *dest, u16 *src, size_t n); +char* sgi_ncpu2a(char *dest, u16 *src, size_t n); +u16* sgi_ncpa2u(u16 *dest, char *src, size_t n); +u16* sgi_ncat16(u16 *dest, u16 c, size_t n); +u16* sgi_rdel16(u16 *dest, size_t n); +s32 sgi_isdigit16(u16 text); +s32 sgi_utol(u16 *text, s32 base); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/sgi_types.h b/src/sgi_types.h new file mode 100644 index 0000000..c725c74 --- /dev/null +++ b/src/sgi_types.h @@ -0,0 +1,40 @@ +#ifndef SGI_TYPES_H +#define SGI_TYPES_H + +#include + +/* Base type redefine */ +#undef u32 +#define u32 unsigned int + +#undef u16 +#define u16 unsigned short + +#undef u8 +#define u8 unsigned char + +#undef s32 +#define s32 int + +#undef s16 +#define s16 short + +#undef s8 +#define s8 signed char + +#undef w32 +#define w32 wchar_t + +#undef SOCKET +#define SOCKET int + +/* Math macro define */ +#define COUNTOF(a) (sizeof(a) / sizeof((a)[0])) + +/* Common define */ +#undef FAIL +#define FAIL -1 +#define COMM_ERR -1 +#define CANCEL_ERR -2 + +#endif \ No newline at end of file diff --git a/src/uart.cpp b/src/uart.cpp new file mode 100644 index 0000000..b5d9a48 --- /dev/null +++ b/src/uart.cpp @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include "global_func.h" + +static int s_fd = -1; + +s32 open_comm(void) +{ + struct termios option; + + /* open serial port */ + s_fd = open("/dev/ttySAC2", O_RDWR | O_NOCTTY); + if (s_fd == -1) { + printf("Can not open ttySAC2!\n"); + return COMM_ERR; + } + + /* set serial port parameter (B115200, 8 , N , 1) */ + tcgetattr(s_fd, &option); + cfmakeraw(&option); + cfsetispeed(&option, B115200); + cfsetospeed(&option, B115200); + tcsetattr(s_fd, TCSANOW, &option); + + return 0; +} + +void close_comm(void) +{ + close(s_fd); +} + +s32 transfer(u8 *tx, u32 tx_len, u8 *rx, u32 rx_len, u32 timeout) +{ + s32 remain; + s32 s; + u8 *p; + s32 status; + fd_set rd; + struct timeval tv; + + /* flush data */ + tcflush(s_fd, TCIOFLUSH); + + /* send data */ + if (write(s_fd, tx, tx_len) < (s32)tx_len) { + return COMM_ERR; + } + +#if 0 + /* receive data */ + FD_ZERO(&rd); + FD_SET(s_fd, &rd); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + timeout = SDL_GetTicks() + timeout; + if (select(s_fd + 1, &rd, NULL, NULL, &tv) <= 0) { + return COMM_ERR; + } +#endif + + /* receive data until enough or timeout */ + p = rx; + remain = rx_len; + timeout = SDL_GetTicks() + timeout; + while (remain > 0 && SDL_GetTicks() < timeout) { + /* cancel operate if need */ + if (fpr_get_cancel_flag()) { + return CANCEL_ERR; + } + SDL_Delay(10); + + /* get serial port data length */ + status = 0; + if (ioctl(s_fd, FIONREAD, &status) < 0) { + continue; + } + + /* read data if has data */ + if (status > 0) { + s = status > remain ? remain : status; + s = read(s_fd, p, s); + p += s; + remain -= s; + } + } + + /* not enough data */ + if (remain > 0) { + return COMM_ERR; + } + + return 0; +} + +s32 uart_receive(u8 *rx, u32 rx_len, u32 timeout) +{ + s32 remain; + s32 s; + u8 *p; + s32 status; + fd_set rd; + struct timeval tv; + + /* receive data */ + FD_ZERO(&rd); + FD_SET(s_fd, &rd); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + timeout = SDL_GetTicks() + timeout; + if (select(s_fd + 1, &rd, NULL, NULL, &tv) <= 0) { + return COMM_ERR; + } + + /* receive data until enough or timeout */ + p = rx; + remain = rx_len; + while (remain > 0 && SDL_GetTicks() < timeout) { + status = 0; + if (ioctl(s_fd, FIONREAD, &status) < 0) { + continue; + } + + if (status > 0) { + s = status > remain ? remain : status; + s = read(s_fd, p, s); + p += s; + remain -= s; + } + SDL_Delay(10); + } + + /* not enough data */ + if (remain > 0) { + return COMM_ERR; + } + + return 0; +} + diff --git a/src/udisk.cpp b/src/udisk.cpp new file mode 100644 index 0000000..d8d4ce7 --- /dev/null +++ b/src/udisk.cpp @@ -0,0 +1,163 @@ +#include "global_def.h" +#include +#include +#include +#include + +#define SKIP_WS(s) \ +do { \ + while (isspace(*s) && s++); \ +} while (0) + +#define FIND_QT(s) \ +do { \ + while (*s != ':' && s++); \ +} while (0) + +s32 udisk_remove_detect(void) +{ + if (access("/udisk", F_OK) != 0) { + return 1; + } + + return 0; +} + +static s32 get_udisk_info(const char *path, struct udisk_info *udisk) +{ + char buf[1024]; + + FILE *fp = fopen(path, "r"); + if (fp == NULL) { + return -1; + } + + memset(udisk, 0, sizeof(struct udisk_info)); + while (fgets(buf, sizeof(buf), fp)) { + char *p = buf; + SKIP_WS(p); + if (strncmp(p, "Vendor", 6) == 0) { + FIND_QT(p); + char *p1 = strtok(p + 2, "\n"); + strncpy(udisk->vendor, p1, sizeof(udisk->vendor) - 1); + } + else if (strncmp(p, "Product", 7) == 0) { + FIND_QT(p); + char *p1 = strtok(p + 2, "\n"); + strncpy(udisk->product, p1, sizeof(udisk->product) - 1); + } + else if (strncmp(p, "Serial Number", 13) == 0) { + FIND_QT(p); + char *p1 = strtok(p + 2, "\n"); + strncpy(udisk->sn, p1, sizeof(udisk->sn) - 1); + } + } + + fclose(fp); + return 0; +} + +static s32 get_udisk_space(const char *path, struct udisk_info *udisk) +{ + struct statfs s; + + if (statfs(path, &s) == -1) { + return -1; + } + + udisk->total = (long long)s.f_blocks * s.f_bsize / 1024 / 1024; + udisk->avail = (long long)s.f_bavail * s.f_bsize / 1024 / 1024; + + return 0; +} + +s32 udisk_insert_detect(struct udisk_info *udisk) +{ + DIR *d; + struct dirent *file; + struct stat sb; + char path[64] = UDISK_DRV; + + if(!(d = opendir(path))) { + return -1; + } + + while((file = readdir(d)) != NULL) { + if(strncmp(file->d_name, ".", 1) == 0) { + continue; + } + + sprintf(path, "%s/%s", path, file->d_name); + if (stat(path, &sb) < 0) { + continue; + } + + if (S_ISREG(sb.st_mode)) { + if (get_udisk_info(path, udisk) == 0) { + /* wait mount is ok */ + int i; + int found = 0; + for (i = 0; i < 5; ++i) { + if (access(UDISK_DEV, F_OK) == 0) { + found = 1; + break; + } + SDL_Delay(500); + } + + if (!found) { + break; + } + + SDL_Delay(1000); + closedir(d); + return get_udisk_space(UDISK_DEV, udisk); + } + } + } + closedir(d); + + return -1; +} + +#if 0 +int main(int argc, char **argv) +{ + int exist = 0; + int i = 0; + + while (i++ < 30) { + if (!exist) { + if (udisk_insert_detect(&s_udisk) == 0) { + exist = 1; + printf("Vendor: %s\n", s_udisk.vendor); + printf("Product: %s\n", s_udisk.product); + printf("Serial number: %s\n", s_udisk.sn); + + if (s_udisk.total > 1024) { + printf("Total: %.2f GB\n", s_udisk.total / 1024.0); + } + else { + printf("Total: %d MB\n", s_udisk.total); + } + + if (s_udisk.avail > 1024) { + printf("Avail: %.2f GB\n", s_udisk.avail / 1024.0); + } + else { + printf("Avail: %d MB\n", s_udisk.avail); + } + } + } + else { + if (udisk_remove_detect()) { + exist = 0; + printf("Udisk is remove\n"); + } + } + + usleep(1000000); + + } +} +#endif diff --git a/temp/sgi_data.cpp b/temp/sgi_data.cpp new file mode 100644 index 0000000..38b7e62 --- /dev/null +++ b/temp/sgi_data.cpp @@ -0,0 +1,745 @@ +#include +#include +#include +#include +#include "global_func.h" + +static std::vector s_person_vec; +static std::vector s_gun_vec; +static struct sgi_box s_gun_box; +static struct sgi_unit s_unit; +static u8 s_gun_box_info[256] = {0}; + +static void *open_w(const char *name, size_t *size) +{ + int fd; + void *ptr; + + /* 打开文件 */ + if ((fd = open(name, O_RDWR)) < 0) { + return NULL; + } + + *size = lseek(fd, 0, SEEK_END); + ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + /* 关闭文件 */ + close(fd); + + return ptr; +} + +static void close_w(void *ptr, size_t size) +{ + if (ptr) { + munmap(ptr, size); + } +} + +static void *open_r(const char *name, size_t *size) +{ + int fd; + void *ptr; + + /* 打开文件 */ + if ((fd = open(name, O_RDONLY)) < 0) { + return NULL; + } + + *size = lseek(fd, 0, SEEK_END); + ptr = mmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0); + + /* 关闭文件 */ + close(fd); + + return ptr; +} + +static void close_r(void *ptr, size_t size) +{ + if (ptr) { + munmap(ptr, size); + } +} + +static s32 open_person_db(char *dbname, s32 spec) +{ + u32 i; + u32 count; + struct sgi_person_mem person; + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 获取记录数 */ + fseek(fp, 0, SEEK_END); + count = ftell(fp) / sizeof(struct sgi_person); + fseek(fp, 0, SEEK_SET); + + /* 限定最大用户数不能超过65536 */ + count &= 0xffff; + + /* 读取人员数据 */ + for (i = 0; i < count; ++i) { + fread(&person, 1, sizeof(struct sgi_person), fp); + if (spec) { + person.index = (1 << 30) | i; /* super user flag */ + } + else { + person.index = i; + } + s_person_vec.push_back(person); + } + + /* 关闭数据文件 */ + fclose(fp); + + return count; +} + +static s32 open_gun_db(const char *dbname) +{ + u32 i; + u32 count; + struct sgi_gun gun; + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 获取记录数 */ + fseek(fp, 0, SEEK_END); + count = ftell(fp) / sizeof(struct sgi_person); + fseek(fp, 0, SEEK_SET); + + /* 读取人员数据 */ + for (i = 0; i < count; ++i) { + fread(&gun, 1, sizeof(struct sgi_gun), fp); + s_gun_vec.push_back(gun); + } + + /* 关闭数据文件 */ + fclose(fp); + + return count; +} + +static s32 open_gun_box_db(const char *dbname) +{ + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 读取数据 */ + fread(&s_gun_box, 1, sizeof(struct sgi_box), fp); + + /* 关闭数据文件 */ + fclose(fp); + + return 1; +} + +static s32 open_unit_db(const char *dbname) +{ + FILE *fp; + + /* 打开数据文件 */ + fp = fopen(dbname, "rb"); + if (fp == NULL) { + return 0; + } + + /* 读取数据 */ + fread(&s_unit, 1, sizeof(struct sgi_unit), fp); + + /* 关闭数据文件 */ + fclose(fp); + + return 1; +} + +static void update_box_info(u32 *cells) +{ + /* box max cap 128 */ + u32 i,j; + s32 index = 0; + + for (i = 0; i < 4; ++i) { + for (j = 0; j < 32; ++j) { + if ((cells[i] & (1 << j)) == 0) { + continue; + } + + s_gun_box_info[index] |= 2; + index++; + } + } +} + +static void load_gun_box_info(void) +{ + u32 i; + u32 size; + + memset(&s_gun_box_info, 0, sizeof(s_gun_box_info)); + + /* 用枪支登记信息初始枪柜 */ + for (i = 0; i < s_gun_vec.size(); ++i) { + if (s_gun_vec[i].lock_code >= sizeof(s_gun_box_info)) { + continue; + } + + s_gun_box_info[s_gun_vec[i].lock_code] = 1; + } + + /* 用枪支借出信息初始枪柜 */ + struct borrow_ctrl *pcont; + pcont = (struct borrow_ctrl *)open_r(DBR(borrow), &size); + if (pcont == NULL) { + return; + } + + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + update_box_info(pcont->cells); + pcont++; + } + + /* 关闭 */ + close_r(pcont, size); +} + +s32 data_open(void) +{ + u32 count = 0; + + /* 清空人员记录数据 */ + s_person_vec.clear(); + + /* 清空枪支记录数据 */ + s_gun_vec.clear(); + + /* 清空枪柜记录 */ + memset(&s_gun_box, 0, sizeof(struct sgi_box)); + + /* 清空单位信息 */ + memset(&s_unit, 0, sizeof(struct sgi_unit)); + + /* 加载特殊权限人员数据 */ + count += open_person_db(DBD(super), 1); + + /* 加载普通人员数据 */ + count += open_person_db(DBD(person), 0); + + /* 加载枪支信息 */ + open_gun_db(DBD(gun)); + + /* 加载枪柜信息 */ + open_gun_box_db(DBD(gun_box)); + + /* 加载单位信息 */ + open_unit_db(DBD(unit)); + + return count > 0 ? 0 : -1; +} + +void data_close(void) +{ + s_person_vec.clear(); + s_gun_vec.clear(); +} + +s32 search_uid(struct sgi_passport *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_USER + && (s_person_vec[i].person.fpr1 == param || + s_person_vec[i].person.fpr2 == param)) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->dept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_USER + && s_person_vec[i].person.idcard == param) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->dept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 search_mid(struct sgi_passport *pass, s32 type, u32 param) +{ + assert(pass != NULL); + + u32 i; + s32 found = 0; + + if (type == SR_FPR) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_MANAGER + && (s_person_vec[i].person.fpr1 == param || + s_person_vec[i].person.fpr2 == param)) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->mdept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + else if (type == SR_CARD) { + for (i = 0; i < s_person_vec.size(); ++i) { + if (s_person_vec[i].person.level == LV_MANAGER + && s_person_vec[i].person.idcard == param) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + sgi_ncp16(pass->mdept, s_person_vec[i].person.dept, + COUNTOF(s_person_vec[i].person.dept)); + found = 1; + break; + } + } + } + + if (!found) { + return FAIL; + } + + return 0; +} + +s32 verify_user_pwd(struct sgi_passport *pass, u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].person.level != LV_USER + || (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->uid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->name, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + } + r = i; + } + + break; + } + + return r; +} + +s32 verify_manager_pwd(struct sgi_passport *pass, u16 *mid, u16 *pwd) +{ + assert(mid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (s_person_vec[i].person.level != LV_MANAGER + || (sgi_ncmp16(s_person_vec[i].person.uid, mid, + COUNTOF(s_person_vec[i].person.uid)) != 0)) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + if (pass) { + sgi_ncp16(pass->mid, s_person_vec[i].person.uid, + COUNTOF(s_person_vec[i].person.uid)); + sgi_ncp16(pass->mname, s_person_vec[i].person.name, + COUNTOF(s_person_vec[i].person.name)); + } + r = i; + } + + break; + } + + return r; +} + +static s32 verify_all_user_pwd(u16 *uid, u16 *pwd) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) != 0) { + continue; + } + + /* 校验密码 */ + r = PWD_INVALID; + if (sgi_ncmp16(s_person_vec[i].person.pwd, pwd, + COUNTOF(s_person_vec[i].person.pwd)) == 0) { + r = i; + } + + break; + } + + return r; +} + +static s32 search_all_user(u16 *uid) +{ + assert(uid != NULL); + + u32 i; + s32 r = ID_INVALID; + + for (i = 0; i < s_person_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_person_vec[i].person.uid, uid, + COUNTOF(s_person_vec[i].person.uid)) == 0) { + r = i; + break; + } + } + + return r; +} + +static s32 sync_pwd(struct sgi_person_mem *person, u16 *new_pwd) +{ + s32 r = FAIL; + s32 index; + size_t size; + struct sgi_person *ptr = NULL; + + /* 打开数据文件 */ + if (person->index & (1 << 30)) { /* super user */ + ptr = (struct sgi_person *)open_w(DBD(super), &size); + } + else { + ptr = (struct sgi_person *)open_w(DBD(person), &size); + } + + if (ptr == NULL) { + goto err; + } + + /* 修改内容 */ + index = person->index & 0xffff; + if (index > size / sizeof(struct sgi_person)) { + goto err; + } + sgi_ncp16(ptr[r].pwd, new_pwd, COUNTOF(ptr[r].pwd)); + + /* 更新到文件 */ + if (msync(ptr, size, MS_SYNC) != 0) { + goto err; + } + + r = 0; + +err: + /* 关闭文件 */ + close_w(ptr, size); + + return r; +} + +s32 change_pwd(u16 *uid, u16 *old_pwd, u16 *new_pwd) +{ + assert(uid != NULL || old_pwd != NULL || new_pwd != NULL); + + s32 r; + + /* 校验旧密码是否有效 */ + r = verify_all_user_pwd(uid, old_pwd); + if (r < 0) { + return r; + } + + /* 修改为新密码 */ + if (sync_pwd(&s_person_vec[r], new_pwd) != 0) { + return FAIL; + } + + sgi_ncp16(s_person_vec[r].person.pwd, new_pwd, + COUNTOF(s_person_vec[r].person.pwd)); + + return 0; +} + +static s32 sgi_append_data(const char *name, void *data, size_t size) +{ + FILE *fp; + + /* 打开日志文件 */ + if (access(name, R_OK | W_OK) == 0) { + fp = fopen(name, "ab"); + } + else { + fp = fopen(name, "wb"); + } + if (fp == NULL) { + return FAIL; + } + + /* 追加数据 */ + if (fwrite(data, 1, size, fp) < size) { + fclose(fp); + return FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + return 0; +} + +s32 register_person(struct sgi_person_mem *person) +{ + u32 i; + s32 index = 0; + + if (search_all_user(person->person.uid) != ID_INVALID) { + /* user exist */ + return ID_EXIST; + } + + if (sgi_append_data(DBD(person), person, + sizeof(struct sgi_person)) != 0) { + return FAIL; + } + + /* 追加到列表 */ + for (i = 0; i < s_person_vec.size(); ++i) { + if ((s_person_vec[i].index & (1 << 30)) == 0) { /* normal user */ + index++; + } + } + person->index = index; + s_person_vec.push_back(*person); + + return 0; +} + +static s32 search_gun(u16 *code) +{ + assert(code != NULL); + + u32 i; + s32 r = CODE_INVALID; + + for (i = 0; i < s_gun_vec.size(); ++i) { + /* 匹配编号 */ + if (sgi_ncmp16(s_gun_vec[i].code, code, + COUNTOF(s_gun_vec[i].code)) == 0) { + r = i; + break; + } + } + + return r; +} + +s32 register_gun(struct sgi_gun *gun) +{ + if (search_gun(gun->code) != CODE_INVALID) { /* gun exist */ + return FAIL; + } + + if (sgi_append_data(DBD(gun), gun, + sizeof(struct sgi_gun)) != 0) { + return FAIL; + } + + /* 追加到列表 */ + s_gun_vec.push_back(*gun); + + return 0; +} + +s32 register_box(struct sgi_box *box) +{ + FILE *fp; + const char *name = DBD(gun_box); + + /* 打开文件 */ + fp = fopen(name, "wb"); + if (fp == NULL) { + return FAIL; + } + + /* 写入数据 */ + if (fwrite(box, 1, sizeof(struct sgi_box), fp) < sizeof(struct sgi_box)) { + fclose(fp); + return FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + /* */ + memcpy(&s_gun_box, box, sizeof(struct sgi_box)); + + return 0; +} + +s32 register_unit(struct sgi_unit *unit) +{ + FILE *fp; + const char *name = DBD(unit); + + /* 打开文件 */ + fp = fopen(name, "wb"); + if (fp == NULL) { + return FAIL; + } + + /* 写入数据 */ + if (fwrite(unit, 1, sizeof(struct sgi_unit), fp) < sizeof(struct sgi_unit)) { + fclose(fp); + return FAIL; + } + + /* 关闭文件 */ + fclose(fp); + + /* */ + memcpy(&s_unit, unit, sizeof(struct sgi_unit)); + + return 0; +} + +struct sgi_box *get_box_info(void) +{ + return &s_gun_box; +} + +struct sgi_unit *get_unit_info(void) +{ + return &s_unit; +} + +s32 enroll_borrow(struct sgi_passport *pass, u32 *cells) +{ + ///* 4 x sizeof(u32) x 8 = 128 bit = box-cap */ + struct borrow_ctrl content; + const char *dbname = DBR(borrow); + + memset(&content, 0, sizeof(struct borrow_ctrl)); + sgi_cp16(content.uid, pass->uid); + memcpy(content.borrow_time, pass->borrow_time, + sizeof(content.borrow_time)); + memcpy(content.return_time, pass->return_time, + sizeof(content.return_time)); + memcpy(content.cells, cells, sizeof(content.cells)); + + if (sgi_append_log(dbname, &content, sizeof(struct borrow_ctrl)) != 0) { + return FAIL; + } + + /* 更新枪柜实时记录 */ + update_box_info(cells); + + return 0; +} + +s32 enroll_return(struct sgi_passport *pass, u32 *cells) +{ + ///* 4 x sizeof(u32) x 8 = 128 bit = box-cap */ + u32 i; + u32 size; + s32 r = FAIL; + struct borrow_ctrl *pcont; + const char *dbname = DBR(borrow); + + pcont = (struct borrow_ctrl *)open_w(dbname, &size); + if (pcont == NULL) { + goto err; + } + + for (i = 0; i < size / sizeof(struct borrow_ctrl); ++i) { + if (sgi_ncmp16(pcont->uid, pass->uid, COUNTOF(pcont->uid)) == 0) { + pcont->cells[0] ^= cells[0]; + pcont->cells[1] ^= cells[1]; + pcont->cells[2] ^= cells[2]; + pcont->cells[3] ^= cells[3]; + } + } + + /* 更新到文件 */ + if (msync(pcont, size, MS_SYNC) != 0) { + goto err; + } + + /* 更新枪柜实时记录 */ + update_box_info(cells); + + r = 0; +err: + if (pcont) { + close_w(pcont, size); + } + + return r; +} diff --git a/temp/sgi_data.h b/temp/sgi_data.h new file mode 100644 index 0000000..cffaeec --- /dev/null +++ b/temp/sgi_data.h @@ -0,0 +1,87 @@ +#ifndef SGI_DATA_H +#define SGI_DATA_H + +#include "sgi_types.h" + +struct sgi_person { + u16 uid[16]; + u16 name[16]; + u16 sex; + u16 age; + u16 dept[16]; + u16 post[16]; + u16 gun[16]; + u16 gun_code[16]; + u16 lock_code; + u16 level; + u16 fpr1; + u16 fpr2; + u32 idcard; + u16 pwd[16]; + u16 phone[16]; +}; + +struct sgi_person_mem { + struct sgi_person person; + s32 index; +}; + +struct sgi_gun { + u16 code[16]; + u16 model[16]; + u16 caliber[8]; + u16 bullet[8]; + u16 holder[16]; + u16 unit[16]; + u16 stock_date[16]; + u16 lock_code; + u16 status; +}; + +struct sgi_bullet { + u16 name[16]; + u16 model[16]; + u16 for_gun[16]; + u16 amount; + u16 lock_code; + u16 batch[16]; + u16 unit[16]; +}; + +struct sgi_box { + u16 type; + u16 cap; + u16 code[16]; + u16 model[16]; + u16 manager[16]; + u16 unit[16]; +}; + +struct sgi_unit { + u16 name[16]; + u16 addr[32]; + u16 dept[16]; + u16 parent[16]; +}; + +struct sgi_passport { + u32 visit; + u16 uid[16]; + u16 name[16]; + u16 dept[16]; + u16 mid[16]; + u16 mname[16]; + u16 mdept[16]; + char photo[64]; + u32 borrow_time[2]; + u32 return_time[2]; +}; + +struct borrow_ctrl { + u16 uid[16]; + u32 borrow_time[2]; + u32 return_time[2]; + u32 cells[4]; +}; + +#endif diff --git a/templet/fm_xxx.cpp b/templet/fm_xxx.cpp new file mode 100644 index 0000000..ab92f88 --- /dev/null +++ b/templet/fm_xxx.cpp @@ -0,0 +1,122 @@ +#include +#include "global_func.h" + +#define MODULE_NAME fm_xxx + +FORM_MODULE(MODULE_NAME); /* */ + +static union sgi_object s_wnd_main; /* 主窗口 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = gmtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + sgi_form_show(&FORM_CLASS(fm_main)); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(MODULE_NAME) +{ + wchar_t buf[64]; + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&FORM_CLASS(MODULE_NAME)); + FORM_CLASS(MODULE_NAME).name = FORM_NAME(MODULE_NAME); + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, FORM_CLASS(MODULE_NAME), 0, 0, 800, 480, 0, + "wnd11.png", IMG_OPTIMIZE, NULL); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, FORM_CLASS(MODULE_NAME), 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, g_sgi_form_get_003, 600, 50, 200, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, g_sgi_form_get_003, 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btnf120.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, g_sgi_form_get_003, 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btnf124.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(FORM_CLASS(MODULE_NAME), s_wnd_main); + + return 0; +} + +FORM_DESTROY_FN(MODULE_NAME) +{ + FORM_CLASS(MODULE_NAME).deinit(&FORM_CLASS(MODULE_NAME)); +} diff --git a/templet/grid-temp.c b/templet/grid-temp.c new file mode 100644 index 0000000..ebd2238 --- /dev/null +++ b/templet/grid-temp.c @@ -0,0 +1,108 @@ +struct cols_info { + u16 type; + s16 x; + s16 y; + s16 w; + s16 h; +}; + +struct grid_cell { + u16 state; + s16 val; + u16 string[64]; +}; + +struct grid_cell { + u16 type; + s16 x; + s16 y; + s16 w; + s16 h; + u16 state; + s32 val; + u16 string[32]; +}; + ++(object)->active_image; ++(object)->pos; ++(object)->readonly; +#define GRID_STRING +#define GRID_BUTTON +#define GRID_RADIO + + +struct grid_cell *cells; + +object->cells = (struct grid_cell *)calloc(sizeof(struct grid_cell), + object->col * object->row); + +free(cells); + +void init_grid(struct draw_grid *object) +{ + u32 i,j; + s32 y0; + + for (i = 0; i < object->row; ++i) { + y0 = object->y + i * RH + Y0; + for (j = 0; j < object->col; ++j) { + switch (j) { + case 0: /* column 0 */ + object->cells[i * object->col + j].type = T; + object->x = object->x + X0; + object->y = y0; + object->w = CW0; + object->h = RH; + break; + + case 1: /* column 1 */ + object->cells[i * object->col + j].type = T; + object->x = object->x + X1; + object->y = y0; + object->w = CW1; + object->h = RH; + break; + + case 2: /* column 2 */ + break; + + default: + break; + } + } + } +} + +void grid_load_data(struct draw_grid *object) +{ + u32 i,j; + struct data *p = s_data; + s32 record_nums = s_data_nums; + + for (i = 0; i < object->row; ++i) { + for (j = 0; j < object->col; ++j) { + switch (j) { + case 0: /* column 0 */ + object->cells[i * object->col + j].string = p->data; + break; + + case 1: + break; + + case 2: + break; + + default: + break; + + } + } + + if (record_nums-- <= 0) { + break; + } + p++; + + } +} + diff --git a/templet/sgi_form_xxx.cpp b/templet/sgi_form_xxx.cpp new file mode 100644 index 0000000..7903a7e --- /dev/null +++ b/templet/sgi_form_xxx.cpp @@ -0,0 +1,121 @@ +#include +#include "global_func.h" + +struct sgi_form g_sgi_form_xxx; /* */ + +static union sgi_object s_wnd_main; /* 主窗体 */ +static union sgi_object s_lbl_date; /* 日期标签 */ +static union sgi_object s_lbl_time; /* 倒计时标签 */ +static union sgi_object s_btn_back; /* 返回按钮 */ +static union sgi_object s_btn_main; /* 首页按钮 */ + +static s32 s_timer = 0; + +static void form_enter(struct sgi_form *) +{ + s_timer = 60; +} + +static s32 lbl_date_frame(struct sgi_label *label) +{ + static u32 next; + time_t now; + struct tm *tmlocal; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + time(&now); + tmlocal = gmtime(&now); + swprintf(buf, sizeof(buf), L"%d-%02d-%02d %02d:%02d", + tmlocal->tm_year + 1900, tmlocal->tm_mon + 1, + tmlocal->tm_mday, tmlocal->tm_hour, tmlocal->tm_min); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static s32 lbl_time_frame(struct sgi_label *label) +{ + static u32 next; + wchar_t buf[64]; + + if (SDL_GetTicks() > next) { + s_timer--; + if (s_timer <= 0) { + s_btn_main.button.up(&s_btn_main.button); + } + swprintf(buf, sizeof(buf), L"倒计时: %02d", s_timer); + set_object_text_w(label, buf); + label->redraw = 1; + + next = SDL_GetTicks() + 1000; + } + + return 0; +} + +static void btn_main_up(struct sgi_button *) +{ + //sgi_form_show(&g_sgi_form_get_001); +} + +static s32 form_frame(struct sgi_form *form) +{ + do { + + } while (0); + + sgi_form_frame_default(form); + + return 0; +} + +FORM_CREATE_FN(sgi_form_get_003) +{ + SDL_Color color = {255,255,255,0}; + + /* 初始页面容器,加入页面元素 */ + form_memset(&g_sgi_form_xxx); + g_sgi_form_xxx.name = "sgi_form_xxx"; + + /* 窗口背景 */ + WINDOW_CREATE(s_wnd_main, g_sgi_form_get_003, 0, 0, 800, 480, 0, + "wnd13.png", IMG_OPTIMIZE); + + /* 日期时间 */ + LABEL_CREATE(s_lbl_date, g_sgi_form_xxx, 600, 20, 200, 25, 1, + "jht.ttf", 22, color); + s_lbl_date.label.frame = lbl_date_frame; + + /* 倒计时 */ + LABEL_CREATE(s_lbl_time, g_sgi_form_get_003, 600, 50, 200, 40, 1, + "jht.ttf", 20, color); + s_lbl_time.label.frame = lbl_time_frame; + + /* 返回按钮 */ + BUTTON_CREATE(s_btn_back, g_sgi_form_get_003, 34, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btnf120.png", + IMG_OPTIMIZE | IMG_ALPHA); + + /* 首页按钮 */ + BUTTON_CREATE(s_btn_main, g_sgi_form_get_003, 686, 348, 80, 81, 1, + "btn-c-u.png", "btn-c-d.png", "btn-c-d.png", "btnf124.png", + IMG_OPTIMIZE | IMG_ALPHA); + s_btn_main.button.up = btn_main_up; + + /* 创建页面 */ + FORM_CREATE(g_sgi_form_xxx, s_wnd_main); + g_sgi_form_xxx.enter = form_enter; + g_sgi_form_xxx.frame = form_frame; + + return 0; +} + +FORM_DESTROY_FN(sgi_form_xxx) +{ + g_sgi_form_xxx.deinit(&g_sgi_form_xxx); +} -- 2.20.1