11 Commits

Author SHA1 Message Date
Serendipity f897536a45 refactor(config): 更新时间限制为30分钟并调整配置文件存储格式
refactor(globals): 移除不必要的GUI运行状态标志
refactor(gui): 更新注释以反映使用IUP库
refactor(ai): 修改威胁检测逻辑以提升威胁等级
refactor(config): 修改加载和保存配置的时间限制逻辑
refactor(network): 更新默认网络端口常量
refactor(record): 移除冗余注释并增强复盘步骤的合法性检查
2026-05-02 12:24:27 +08:00
Serendipity 249dc2ab4b build(installer): 精简安装包配置并移除NSIS脚本
- 删除 NSIS 安装脚本 (installer.nsi),统一使用 Inno Setup
- 简化 Inno Setup 脚本,仅打包核心运行文件 (gobang_gui.exe, iup.dll) 和记录目录
- 移除源码、文档等开发文件,减小安装包体积
- 更新 README.md 以反映 v9.0 版本变更,专注于图形界面和网络功能
2026-03-17 18:10:40 +08:00
Serendipity 88f12bcfea feat(network): 集成ENet库并实现局域网联机对战功能
- 添加ENet库作为网络通信基础,替换原有的原生Socket实现
- 扩展游戏模式支持局域网联机对战(PvP网络模式)
- 重构网络状态结构以适配ENet的Host/Peer模型
- 在图形界面中添加网络对战菜单,支持创建房间和加入房间
- 实现网络消息的发送与接收,包括落子、断开连接等消息类型
- 为网络对战添加定时器轮询机制,实时处理网络事件
- 更新构建系统以编译和链接ENet库
2026-03-17 17:57:04 +08:00
Serendipity 0c9cfba81b refactor(gui): 拆分大型 GUI 模块为多个功能文件
将单一的 gui.c 文件拆分为 gui_core.c、gui_draw.c、gui_game.c 和 gui_replay.c,并引入 gui_internal.h 作为内部头文件。更新 Makefile 以包含新的源文件。同时修复了复盘模式中主菜单的隐藏时机,并改进了记录文件的加载逻辑以更安全地处理 CSV 解析。

- 提取核心 GUI 初始化、事件循环和坐标转换到 gui_core.c
- 分离绘图功能(棋盘、棋子)到 gui_draw.c
- 将游戏逻辑(PvP/PvE)移动到 gui_game.c
- 独立复盘功能到 gui_replay.c,优化文件选择流程
- 修复 btn_replay_cb 中过早隐藏主菜单的问题
- 增强 load_game_from_file 的健壮性,使用 sscanf 替代 fscanf 并改进行处理
2026-03-17 17:13:46 +08:00
Serendipity dd2b6fd903 refactor: 重构项目为纯GUI版本并清理冗余代码
- 移除控制台版本相关代码,包括game_mode、ui、init_board等模块
- 将empty_board函数移至gobang.c核心模块
- 简化main.c仅保留GUI启动逻辑
- 更新Makefile仅构建GUI版本
- 清理过时文档和配置文件
- 优化GUI菜单和游戏窗口交互逻辑
- 添加AI难度配置支持
2026-03-17 16:57:27 +08:00
Serendipity 0baab8bec6 feat(gui): 添加主菜单和游戏模式选择界面
- 新增 GUI 主菜单,支持玩家对战、人机对战、复盘模式和设置选项
- 新增游戏设置对话框,可配置棋盘大小、禁手、计时器和 AI 难度
- 重构 GUI 游戏窗口,集成悔棋、保存和返回菜单功能
- 更新 Makefile 以支持 PowerShell 并添加新源文件编译
- 调整窗口尺寸为 1000x800 以提供更好的游戏体验
2026-03-17 15:41:48 +08:00
Serendipity d796065bb9 chore: 添加预编译的IUP库文件并更新.gitignore
添加Windows平台所需的IUP GUI库文件至libs目录,包括iupcontrols、iupgl、iupim等核心组件。
同时更新.gitignore文件,优化构建产物和临时文件的忽略规则,将临时游戏存档从*.csv改为records/目录。
2026-03-16 13:28:55 +08:00
Serendipity 1332d14347 docs: 更新项目文档至v8.3并调整.gitignore
- 更新项目要求文档至v8.3版本,说明引入IUP图形库和构建系统优化
- 更新项目简介,详细说明v8.3的图形界面重构和目录结构调整
- 更新GUI说明文档,从SDL3迁移至IUP,并更新编译和运行指南
- 在.gitignore中添加obj目录,避免编译生成的对象文件被提交
2026-03-16 13:26:28 +08:00
Serendipity ec63b6d97c docs: 更新文档以反映项目结构变更和构建系统迁移
- 更新版本号至v8.3,反映图形库迁移至IUP和构建系统引入Makefile
- 重构README.md,重点介绍新的目录结构和Makefile编译方式
- 更新BUILD.md,详细说明新的make命令用法
- 修改main.c中的编译指令示例,从原始gcc命令改为make命令
- 调整gui.c中的注释格式以改善可读性
2026-03-16 13:22:30 +08:00
Serendipity 8bddf6bb37 feat(gui): 迁移图形界面库从SDL3到IUP
- 移除SDL3依赖,引入IUP图形界面库
- 更新Makefile以支持IUP编译配置
- 重构GUI模块,移除SDL相关代码
- 更新全局变量和类型定义,移除SDL依赖
- 添加IUP头文件到项目库目录
- 删除手动帧率控制(SDL_Delay),依赖IUP事件循环
- 更新编译脚本和文档说明
2026-03-16 13:14:01 +08:00
Serendipity a0944f8e16 fix: 修正SDL初始化条件判断和Windows平台编译兼容性
- 将SDL初始化条件从`< 0`改为`!= 0`以正确处理SDL_Init返回值
- 为Windows平台的#pragma comment添加_MSC_VER条件编译,提升跨编译器兼容性
- 统一网络函数参数声明中的指针星号位置,保持代码风格一致
2026-02-09 20:16:52 +08:00
151 changed files with 17094 additions and 4828 deletions
+4 -17
View File
@@ -1,8 +1,6 @@
# 编译生成的可执行文件 # 编译生成的可执行文件
*.exe
*.out *.out
*.app *.app
*.o
# IDE配置文件 # IDE配置文件
.idea/ .idea/
@@ -30,24 +28,13 @@ Thumbs.db
*.ilk *.ilk
# 对象文件 # 对象文件
*.o
*.obj *.obj
# 静态库文件
*.lib
*.a
# 动态库文件
*.dll
*.so
*.dylib
# 资源文件
*.res
*.ico
# 打包文件 # 打包文件
dist/ dist/
# 编译生成的对象文件
obj/
# 临时游戏存档 # 临时游戏存档
*.csv records/
-105
View File
@@ -1,105 +0,0 @@
## 🎯 项目优势
### ✅ 已经做得很好的方面
- 📚 代码质量优秀 :注释覆盖率30.1%,使用Doxygen格式文档
- 🏗️ 架构设计合理 :模块化设计,职责分离清晰
- 🎮 功能完整丰富 :支持人机对战、双人对战、网络对战、GUI界面
- 🔧 技术栈现代化 :SDL3图形库、双版本架构、专业安装包
- 📋 文档完善 :详细的README、AI增强指南、架构重构指南
- 🌐 跨平台考虑 :已有条件编译支持Windows/Linux
## 🚀 改进建议
### 1. 🧪 测试体系建设(高优先级)
当前状况 :项目缺乏自动化测试
建议改进
- 添加单元测试框架(如Unity或自制简单测试框架)
- 为核心模块编写测试用例:AI算法、棋盘逻辑、网络通信
- 添加集成测试验证各模块协作
- 创建性能基准测试
### 2. 🛡️ 错误处理和安全性增强(高优先级)
当前状况 :基础错误处理存在,但可以更完善
建议改进
- 增强输入验证,防止缓冲区溢出
- 添加网络通信的安全验证机制
- 完善内存管理,添加内存泄漏检测
- 增加异常恢复机制
### 3. 🎯 AI算法优化(中优先级)
当前状况 :基础Minimax+α-β剪枝,搜索深度3层
建议改进
- 实现置换表缓存系统
- 添加开局库和残局库
- 实现迭代加深搜索
- 增加威胁检测优化
- 支持多线程并行搜索
### 4. 🔧 构建和部署优化(中优先级)
当前状况 :编译脚本功能完善,但可以更自动化
建议改进
- 添加CMake构建系统支持
- 实现持续集成/持续部署(CI/CD)
- 添加依赖管理和版本控制
- 完善跨平台构建脚本
### 5. 📊 性能监控和分析(中优先级)
建议添加
- AI决策时间统计
- 内存使用监控
- 网络延迟分析
- 性能瓶颈识别工具
### 6. 🎮 用户体验提升(低优先级)
建议改进
- 添加音效和动画效果
- 实现主题和皮肤系统
- 增加游戏统计和成就系统
- 支持自定义快捷键
### 7. 🌐 网络功能增强(低优先级)
建议改进
- 实现房间系统和匹配机制
- 添加观战功能
- 支持断线重连
- 实现聊天系统
## 📋 具体实施建议
### 立即可实施(1-2周)
1. 1.
创建基础测试框架
2. 2.
添加输入验证和边界检查
3. 3.
完善错误日志记录
4. 4.
优化编译警告处理
### 短期目标(1-2月)
1. 1.
完善单元测试覆盖
2. 2.
实现置换表和开局库
3. 3.
添加性能监控
4. 4.
增强网络安全性
### 长期规划(3-6月)
1. 1.
实现神经网络AI
2. 2.
完整跨平台支持
3. 3.
添加数据库支持
4. 4.
实现云端对战
## 🏆 总体评价
你的项目已经达到了 专业级别的开源项目标准 !代码架构清晰、功能完整、文档详尽。主要的改进空间在于测试覆盖和一些高级特性的添加。
项目亮点
- 从v7.0的架构重构到v8.2的编译优化,版本迭代思路清晰
- SDL3图形化界面实现现代化
- 网络对战功能完整
- 代码注释和文档非常专业
这是一个非常值得继续完善和推广的优秀项目!🎉
-157
View File
@@ -1,157 +0,0 @@
# 🧠 五子棋AI实现详解
## 📜 算法概述
本五子棋AI采用α-β剪枝优化的极小极大算法,结合专业的棋型评估系统和多层次的威胁检测机制。v8.0版本新增SDL3图形化界面支持,提供可视化AI决策过程和双版本架构(控制台+GUI)。支持人机对战、双人对战和网络对战多种模式。
```mermaid
graph TD
A[AI决策开始] --> B{威胁检测}
B -->|有威胁| C[防御性落子]
B -->|无威胁| D[α-β剪枝搜索]
D --> E[评估候选位置]
E --> F[选择最优落子]
```
## 🔢 数据结构
### 🎲 棋盘表示
```c
int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; // 25x25最大棋盘
```
- `0` 空位
- `1` 玩家(✖)
- `2` AI(◯)
### 📝 步数记录
```c
typedef struct {
int player; // 1=玩家, 2=AI
int x, y; // 坐标(0-based)
} Step;
Step steps[MAX_STEPS]; // 最大步数记录
```
### 🧭 方向分析
```c
typedef struct {
int continuous_chess; // 连续同色棋子数
bool check_start; // 起始方向开放
bool check_end; // 结束方向开放
} DirInfo;
```
### 🌐 网络对战支持
```c
// 网络模式下的AI决策
void network_ai_move(int depth, int player_id);
// 同步AI决策到网络对手
void sync_ai_decision(int x, int y);
```
### 🎨 GUI界面AI支持 (v8.0新增)
```c
// GUI模式下的AI可视化决策
void gui_ai_move_with_animation(int x, int y);
// 显示AI思考过程
void show_ai_thinking_process(SDL_Renderer* renderer);
// AI决策结果的图形化展示
void render_ai_decision_info(SDL_Renderer* renderer, int score, int depth);
```
## ⚙️ 核心函数
### 1. ai_move(int depth)
```c
void ai_move(int depth);
```
**执行流程**:
1. 🔍 扫描棋盘检测威胁
2. 🛡️ 优先防御关键威胁
3. 🔎 使用α-β剪枝搜索最佳位置
4. ✅ 执行最优落子
### 2. dfs() - α-β剪枝核心
```c
int dfs(int x, int y, int player, int depth, int alpha, int beta, bool is_maximizing);
```
**剪枝条件**:
- 极大节点: α ≥ β
- 极小节点: β ≤ α
### 3. evaluate_pos() - 位置评估
**评分标准**:
| 棋型 | 图示 | 分数 |
|------|------|------|
| 活四 | ○○○○● | 100000 |
| 冲四 | ○○○○■ | 10000 |
| 活三 | ○○○●● | 5000 |
## 🏆 评估系统
### 棋型评分表
| 棋型 | 分数 | 示例 |
|------|------|------|
| 活四 | 100000 | `-----○-----` |
| 冲四 | 10000 | `----○■----` |
| 活三 | 5000 | `---○●●---` |
### 位置权重计算
```python
权重 = 50 * (BOARD_SIZE - |x-center| - |y-center|)
```
## ⚡ 性能优化
1. **评估缓存**:
- 哈希表存储重复位置评估
- 命中率: ~85%
2. **搜索优化**:
- 局部搜索范围: 2格
- 平均剪枝率: 65%
3. **典型搜索深度**:
- 基础难度: 3层
- 最高难度: 5层
4. **网络优化**:
- 异步AI计算,避免网络延迟
- 决策结果实时同步
- 支持断线重连后状态恢复
## 🎯 典型场景
### 必胜局面处理
```
局面: ○○○○_
决策: 立即落子形成五连
```
### 双活三防御
```
威胁: 玩家有两个活三
应对: 必须阻挡关键交叉点
```
## 📊 性能基准
| 指标 | 15x15棋盘 | 19x19棋盘 |
|------|-----------|-----------|
| 平均决策时间 | 120ms | 350ms |
| 最大搜索节点 | 8,200 | 24,500 |
| 平均剪枝率 | 68% | 62% |
## 🛠️ 开发建议
1. **调试技巧**:
- 启用`DEBUG_MODE`查看搜索过程
- 使用`print_board()`可视化评估
- 网络模式下使用`network_debug()`监控通信
2. **扩展方向**:
- 添加开局库
- 实现并行搜索
- 优化评估函数
- 增强网络对战AI适应性
- 支持AI难度动态调整
```
-270
View File
@@ -1,270 +0,0 @@
# 五子棋项目代码架构重构指南
## 📋 概述
本文档详细记录了五子棋项目在v7.0-v8.0版本中进行的重大代码架构重构,包括重构的目标、实施过程、技术细节和带来的改进。v8.0版本新增了SDL3图形化界面模块,实现了双版本架构设计。
## 🎯 重构目标
### 主要目标
1. **代码模块化** - 实现清晰的模块分离和职责划分
2. **配置统一管理** - 集中管理所有配置参数和宏定义
3. **全局变量规范化** - 统一管理全局变量,避免散乱分布
4. **类型定义标准化** - 集中定义所有数据结构和类型
5. **提升可维护性** - 降低代码耦合度,提高可读性和可维护性
6. **双版本架构** - (v8.0新增) 实现控制台版本和GUI版本的并行支持
7. **图形化界面集成** - (v8.0新增) 无缝集成SDL3图形库,提供现代化用户界面
### 预期收益
- 减少代码重复和冗余
- 提高开发效率和调试便利性
- 增强代码的可扩展性和可移植性
- 为后续功能开发奠定坚实基础
## 🏗️ 重构实施
### 1. 配置参数统一管理
#### 重构前状态
- 配置参数散落在多个头文件中
- 存在重复定义和不一致的问题
- 网络相关配置分散在`network.h`
- 缺乏统一的配置管理机制
#### 重构措施
- **集中到config.h**:将所有配置宏定义迁移到`config.h`文件
- **分类管理**:按功能模块对配置参数进行分组
- **消除重复**:移除重复的宏定义,确保唯一性
- **标准化命名**:统一配置参数的命名规范
#### 配置分类结构
```c
// 棋盘配置
#define BOARD_SIZE 15
#define MIN_BOARD_SIZE 5
#define MAX_BOARD_SIZE 25
// 游戏模式配置
#define MODE_HUMAN_VS_AI 1
#define MODE_HUMAN_VS_HUMAN 2
#define MODE_NETWORK_BATTLE 3
// AI参数配置
#define DEFAULT_AI_DEPTH 3
#define MAX_AI_DEPTH 6
#define AI_TIMEOUT_MS 5000
// 网络配置
#define DEFAULT_PORT 8888
#define BUFFER_SIZE 1024
#define MAX_IP_LENGTH 16
// 评分参数
#define SCORE_FIVE 100000
#define SCORE_LIVE_FOUR 10000
#define SCORE_RUSH_FOUR 1000
```
### 2. 全局变量统一管理
#### 重构前状态
- 全局变量分散在各个源文件中
- 缺乏统一的声明和定义管理
- 变量作用域不清晰
- 初始化逻辑分散
#### 重构措施
- **创建globals模块**:新建`globals.h``globals.c`文件
- **集中声明**:在`globals.h`中统一声明所有全局变量
- **集中定义**:在`globals.c`中统一定义和初始化
- **访问规范化**:通过包含`globals.h`访问全局变量
#### 全局变量分类
```c
// 游戏状态变量
extern int current_board[MAX_BOARD_SIZE][MAX_BOARD_SIZE];
extern int current_player;
extern int game_over;
// 配置变量
extern GameConfig game_config;
extern AIConfig ai_config;
extern NetworkConfig network_config;
// 统计变量
extern GameStats game_stats;
extern int total_games_played;
```
### 3. 类型定义标准化
#### 重构前状态
- 结构体定义分散在各个头文件中
- 类型定义不统一
- 缺乏标准的数据结构规范
#### 重构措施
- **创建type.h**:集中定义所有数据结构和类型
- **标准化命名**:采用统一的命名规范
- **逻辑分组**:按功能对类型进行分组
- **文档化**:为每个类型添加详细注释
#### 类型定义结构
```c
// 基础类型定义
typedef enum {
PLAYER_NONE = 0,
PLAYER_BLACK = 1,
PLAYER_WHITE = 2
} PlayerType;
// 游戏配置结构
typedef struct {
int board_size;
int ai_level;
int enable_forbidden;
int time_limit;
} GameConfig;
// 网络消息结构
typedef struct {
int type;
int x, y;
int player;
char data[256];
} NetworkMessage;
```
### 4. 网络配置重构
#### 具体实施
1. **迁移宏定义**:将`network.h`中的配置宏移动到`config.h`
2. **统一命名**:规范网络相关宏的命名
3. **添加引用**:在`network.h`中添加`#include "config.h"`
4. **消息类型统一**:将消息类型定义集中管理
#### 迁移的配置项
```c
// 从network.h迁移到config.h
#define DEFAULT_PORT 8888
#define BUFFER_SIZE 1024
#define MAX_IP_LENGTH 16
#define MSG_MOVE 1
#define MSG_CHAT 2
#define MSG_SURRENDER 3
#define MSG_DISCONNECT 4
```
## 📊 重构效果评估
### 代码质量提升
- **模块耦合度降低**:各模块职责更加清晰
- **代码重复减少**:消除了重复的宏定义和类型定义
- **可读性增强**:统一的命名规范和代码结构
- **维护性提高**:集中管理使得修改更加便捷
### 开发效率提升
- **配置修改便捷**:只需在一个地方修改配置参数
- **调试更容易**:全局变量集中管理,状态更清晰
- **扩展更简单**:标准化的接口和数据结构
- **错误减少**:统一管理避免了不一致性错误
### 性能影响
- **编译时间**:略有增加(由于更多的头文件包含)
- **运行时性能**:无显著影响
- **内存使用**:无显著变化
- **整体评估**:性能影响微乎其微,收益远大于成本
## 🔧 技术细节
### 文件结构变化
#### 新增文件
- `type.h` - 类型定义集中文件
- `globals.h` - 全局变量声明文件
- `globals.c` - 全局变量定义文件
#### 修改文件
- `config.h` - 扩展为完整的配置管理文件
- `network.h` - 移除配置定义,添加config.h引用
- 所有源文件 - 更新头文件包含关系
### 编译依赖关系
```
type.h (基础类型)
config.h (配置参数)
globals.h (全局变量声明)
各功能模块头文件
源文件实现
```
### 包含关系规范
1. **type.h**:被所有需要类型定义的文件包含
2. **config.h**:被所有需要配置参数的文件包含
3. **globals.h**:被所有需要访问全局变量的文件包含
4. **功能模块头文件**:按需包含上述基础头文件
## 📝 最佳实践
### 配置管理
1. **新增配置参数**:统一添加到`config.h`的相应分组中
2. **命名规范**:使用描述性的宏名称,避免缩写
3. **分组管理**:按功能模块对配置进行逻辑分组
4. **文档注释**:为每个配置参数添加清晰的注释
### 全局变量管理
1. **声明规范**:在`globals.h`中使用extern声明
2. **定义规范**:在`globals.c`中进行实际定义和初始化
3. **访问规范**:通过包含`globals.h`访问,避免重复声明
4. **初始化管理**:在`globals.c`中集中进行初始化
### 类型定义管理
1. **命名规范**:使用PascalCase命名结构体和枚举
2. **分组管理**:按功能对类型进行逻辑分组
3. **文档化**:为每个类型和字段添加详细注释
4. **版本兼容**:考虑结构体的向后兼容性
## 🚀 未来扩展
### 短期计划
1. **配置文件增强**:支持更多配置项的动态加载
2. **类型安全增强**:添加更多的类型检查和验证
3. **模块接口标准化**:定义标准的模块接口规范
### 长期规划
1. **插件架构**:基于当前架构实现插件系统
2. **配置热重载**:支持运行时配置的动态更新
3. **跨平台适配**:利用统一架构实现跨平台支持
## 📚 参考资料
### 相关文档
- [C语言编程规范](https://www.kernel.org/doc/html/latest/process/coding-style.html)
- [软件架构设计原则](https://en.wikipedia.org/wiki/Software_architecture)
- [模块化编程最佳实践](https://en.wikipedia.org/wiki/Modular_programming)
### 工具推荐
- **静态分析**:使用cppcheck进行代码质量检查
- **格式化**:使用clang-format统一代码格式
- **文档生成**:使用Doxygen生成API文档
## 📈 总结
v7.0版本的代码架构重构是一次重要的技术升级,通过系统性的重构实现了:
**配置参数的统一管理** - 提高了配置的一致性和可维护性
**全局变量的规范化** - 降低了代码的复杂度和耦合度
**类型定义的标准化** - 增强了代码的可读性和类型安全
**模块结构的优化** - 为后续功能扩展奠定了坚实基础
这次重构不仅解决了当前的技术债务,更为项目的长期发展提供了良好的架构基础。后续的功能开发将能够更加高效和稳定地进行。
---
*本文档将随着项目的发展持续更新,记录架构演进的每一个重要节点。*
-73
View File
@@ -1,73 +0,0 @@
# 五子棋游戏编译指南
本项目现在支持使用 `make` 命令进行编译,提供了更便捷的构建方式。
## 系统要求
- MinGW64 编译器
- SDL3 开发库(用于图形界面)
- Make 工具
## 编译命令
### 查看所有可用命令
```bash
make help
```
### 编译所有版本
```bash
make all
```
这将同时编译控制台版本和GUI版本。
### 只编译控制台版本
```bash
make console
```
生成 `gobang_console.exe`
### 只编译GUI版本
```bash
make gui
```
生成 `gobang_gui.exe`
### 清理编译文件
```bash
make clean
```
删除所有目标文件(.o)和可执行文件(.exe)
### 编译并运行
```bash
# 编译并运行控制台版本
make run-console
# 编译并运行GUI版本
make run-gui
```
## 生成的文件
- `gobang_console.exe` - 控制台版本,支持所有功能包括图形界面模式
- `gobang_gui.exe` - GUI版本,与控制台版本功能相同
## 注意事项
1. 两个版本都包含完整功能,包括图形界面支持
2. 需要确保SDL3库路径正确配置在Makefile中
3. 编译时会显示一些警告,这是正常的
4. 如果遇到编译错误,请检查MinGW64和SDL3的安装路径
## 传统编译方式
如果不使用Makefile,仍可以使用传统的gcc命令:
```bash
# 控制台版本
gcc -std=c17 -o gobang.exe *.c -lws2_32
# GUI版本
gcc -std=c17 -o gobang_gui.exe *.c -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
```
-78
View File
@@ -1,78 +0,0 @@
# 为五子棋游戏添加图标指南
## 问题说明
在尝试为可执行文件添加图标时,发现icon文件夹中的图标文件格式不正确:
- `gobang_icon1.ico``gobang_icon2.ico` 实际上是HTML文件和PNG文件,而不是真正的ICO格式文件
## 解决方案
### 方法一:获取正确的ICO文件
1. **下载或创建真正的ICO文件**
- 使用在线ICO转换工具将PNG/JPG转换为ICO格式
- 推荐网站:https://www.icoconverter.com/
- 或使用GIMP、Photoshop等图像编辑软件导出ICO格式
2. **替换现有文件**
- 将正确的ICO文件保存为 `icon/gobang_icon.ico`
- 确保文件是真正的ICO格式(文件头应为 00 00 01 00)
3. **修改资源文件**
- 编辑 `gobang.rc` 文件
- 取消注释图标行:`IDI_APPLICATION ICON "icon\\gobang_icon.ico"`
4. **重新编译**
```bash
windres gobang.rc -o gobang.res
gcc -std=c17 -o gobang.exe *.c gobang.res -lws2_32
```
### 方法二:使用现有PNG文件(需要转换)
如果你有PNG格式的图标文件,可以:
1. **在线转换**
- 访问 https://convertio.co/png-ico/
- 上传PNG文件并转换为ICO格式
- 下载转换后的ICO文件
2. **使用ImageMagick(如果已安装)**
```bash
magick convert icon/your_image.png icon/gobang_icon.ico
```
### 方法三:使用Windows资源编辑器
1. 编译不带图标的exe文件(当前状态)
2. 使用Resource Hacker等工具后期添加图标
3. 下载Resource Hackerhttp://www.angusj.com/resourcehacker/
## 当前状态
- ✅ 程序可以正常编译和运行
- ✅ 包含版本信息资源
- ❌ 暂时没有应用程序图标
- ✅ 提供了完整的构建脚本
## 编译指令
### 不带图标版本(当前可用)
```bash
gcc -std=c17 -o gobang.exe *.c -lws2_32
```
### 带图标版本(需要正确的ICO文件)
```bash
windres gobang.rc -o gobang.res
gcc -std=c17 -o gobang.exe *.c gobang.res -lws2_32
```
## 验证ICO文件格式
可以使用以下PowerShell命令检查文件是否为真正的ICO格式:
```powershell
Get-Content icon/gobang_icon.ico -AsByteStream -TotalCount 4 | ForEach-Object { '{0:X2}' -f $_ }
```
正确的ICO文件应该显示:`00 00 01 00`
-150
View File
@@ -1,150 +0,0 @@
# 五子棋网络对战使用说明
## 功能概述
本项目支持网络对战功能,允许两台设备通过网络进行实时五子棋对战,支持服务器/客户端连接。v8.0版本新增了GUI界面的网络对战支持,提供更直观的可视化网络游戏体验。
### v8.2 (2025-10-08)
- 专业安装包制作 - 支持Inno Setup和NSIS双重安装方案
- 安装程序优化 - 完整的文件打包和快捷方式创建
- 分发体系完善 - 提供标准化的软件分发解决方案
- 用户体验提升 - 一键安装部署,支持完整卸载功能
## 编译方法
### 控制台版本
```bash
gcc -std=c17 -o gobang.exe *.c -lws2_32
```
### GUI版本
```bash
gcc -std=c17 -o gobang_gui.exe *.c -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
copy "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\bin\SDL3.dll" .
```
**注意:**
- Windows系统需要添加 `-lws2_32` 链接库
- GUI版本需要SDL3库支持
- Linux系统不需要ws2_32链接库参数
## 使用方法
### 1. 启动游戏
运行编译后的程序
```bash
.\gobang.exe
```
### 2. 选择网络对战模式
在主菜单中选择 `3. 网络对战`
### 3. 选择连接模式
#### 模式1:创建房间(作为服务器)
- 选择 `1. 创建房间(作为服务器)`
- 输入监听端口(默认8888,建议使用1024-65535范围内的端口)
- 程序会显示本机IP地址,将此IP告知对方
- 等待对方连接
#### 模式2:加入房间(连接到服务器)
- 选择 `2. 加入房间(连接到服务器)`
- 输入服务器IP地址
- 输入服务器的端口号(与服务器设置的端口一致)
- 连接到服务器
### 4. 开始游戏
- 连接成功后游戏自动开始
- 服务器为玩家1(黑棋),客户端为玩家2(白棋)
- 玩家1先手
## 游戏操作
### 基本操作
- **落子**:输入坐标 `行号 列号`,例如:`7 7`
- **认输**:输入 `S``s`
- **悔棋**:输入 `R``r`(需要对方同意)
### 网络功能
- **自动同步**:落子操作会自动同步给对方
- **连接检测**:自动检测网络连接状态
- **延时显示**:支持回合延时显示,避免过快操作
- **悔棋协商**:悔棋需要对方同意才能生效
## 网络配置
### 端口设置
- 默认端口:8888
- 可设端口范围:1024-65535
- 确保防火墙允许选定端口的通信
### IP地址
- **局域网**:使用内网IP地址,例如:192.168.1.100
- **广域网**:使用公网IP地址,可能需要路由器端口转发
### 防火墙设置
如果连接失败,请检查防火墙设置:
#### Windows防火墙
1. 打开Windows安全中心
2. 选择"防火墙和网络保护"
3. 选择"允许应用通过防火墙"
4. 添加gobang.exe到允许列表
#### 路由器设置(用于广域网对战)
如果通过互联网对战,可能需要:
1. 在路由器中设置端口转发
2. 将选定端口转发到服务器内网IP
3. 将路由器的公网IP告知对方
## 故障排除
### 常见问题
1. **连接失败**
- 检查IP地址和端口是否正确
- 确认防火墙设置
- 确保两台设备网络连通
2. **游戏中断**
- 检查网络连接稳定性
- 重新启动游戏重新连接
3. **端口被占用**
- 更换其他端口号
- 关闭占用端口的其他程序
### 网络测试
可以使用以下命令测试网络连通性:
```bash
# 测试网络连通
ping <对方IP地址>
# 测试端口(需要telnet客户端)
telnet <对方IP地址> <端口号>
```
## 技术细节
- **协议**TCP/IP
- **消息格式**:自定义二进制协议
- **支持功能**
- 棋盘同步
- 悔棋处理
- 认输协商
- 连接检测
- 延时控制
## 安全注意事项
1. **局域网使用**:建议安全的家庭或办公环境
2. **广域网使用**
- 不要使用默认端口8888
- 游戏结束后及时关闭程序
- 注意保护个人网络信息
**开发者:** 刘航宇
**联系邮箱:** 3364451258@qq.com
**项目主页:** https://github.com/LHY0125/Gobang-Game
-147
View File
@@ -1,147 +0,0 @@
# 五子棋游戏 - 图形化界面说明 (v8.0)
## 概述
v8.0版本实现了完整的双版本架构,支持两种界面模式:
- **控制台界面**:传统的文本界面,保持原有功能完整性
- **图形化界面**:基于SDL3的现代图形界面,提供可视化操作体验
## v8.0新增功能
-**SDL3图形化界面**:现代化的可视化棋盘
-**鼠标交互支持**:点击落子,直观操作
-**窗口管理优化**:自动居中,响应式设计
-**事件驱动架构**:流畅的用户交互体验
-**安装包支持**:提供专业的安装程序
-**双版本并行**:控制台和GUI版本独立运行
## 环境要求
### SDL3库配置
1. 下载SDL3-3.2.22开发库
2. 解压到:`D:\settings\SDL\SDL3-3.2.22\`
3. 确保目录结构如下:
```
D:\settings\SDL\SDL3-3.2.22\
├── x86_64-w64-mingw32\
│ ├── include\ # 头文件
│ ├── lib\ # 库文件
│ └── bin\ # DLL文件
└── ...
```
### 编译环境
- GCC编译器(MinGW-w64)位于:`D:\Program Files\mingw64`
- Windows 10/11操作系统
- 支持OpenGL的显卡驱动
## 编译方法
### 方法一:使用批处理脚本(推荐)
```bash
# 编译图形化版本
.\compile_gui.bat
```
### 方法二:手动编译
```bash
# 控制台版本
gcc -std=c17 -o gobang.exe *.c -lws2_32
# 图形化版本
gcc -std=c17 -o gobang_gui.exe *.c -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
# 复制SDL3.dll到当前目录
copy "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\bin\SDL3.dll" .
```
## 运行方法
### 控制台版本
```bash
.\gobang.exe
```
在主菜单选择模式1-7进行游戏
### 图形化版本
```bash
.\gobang_gui.exe
```
在主菜单选择模式8启动图形化界面
## 图形化界面功能
- **窗口大小**800x600像素
- **棋盘显示**:15x15标准五子棋棋盘,木质纹理背景
- **鼠标操作**:点击棋盘交叉点进行落子
- **键盘操作**
- `ESC`:退出图形化界面返回主菜单
- `R`:重新开始游戏
- `U`:撤销上一步(如果支持)
- **游戏状态**
- 实时显示当前玩家(黑子/白子)
- 显示游戏进度和状态
- 胜负结果提示
- **视觉效果**
- 黑白棋子带阴影效果
- 当前玩家指示器
- 平滑的图形渲染
- **胜负判定**:自动检测五子连珠并显示获胜者
## 故障排除
### 编译错误
1. **找不到SDL3头文件**
- 检查SDL3库路径是否正确
- 确保include目录存在
2. **链接错误**
- 检查lib目录是否存在
- 确保SDL3.lib文件存在
3. **运行时错误**
- 确保SDL3.dll在系统PATH中或与exe文件同目录
### 图形化界面启动失败
- 检查SDL3库是否正确安装在指定路径
- 确保SDL3.dll文件在exe同目录下
- 检查显卡驱动是否支持OpenGL
- 尝试以管理员权限运行
- 确认Windows版本兼容性
### 运行时问题
- **窗口无法显示**:检查显示器分辨率设置
- **鼠标点击无响应**:确认点击在棋盘交叉点附近
- **游戏卡顿**:关闭其他占用GPU的程序
## 使用说明
### 快速开始
1. 运行 `compile_gui.bat` 编译图形化版本
2. 运行 `gobang_gui.exe` 启动程序
3. 在主菜单选择 "8. 图形化界面"
4. 使用鼠标点击棋盘进行游戏
5. 按ESC键退出图形化界面
### 游戏规则
- 黑子先行,轮流落子
- 率先形成五子连珠者获胜
- 支持横、竖、斜四个方向的连珠判定
## 开发说明
### 文件结构
- `gui.h` - 图形化界面头文件
- `gui.c` - 图形化界面实现
- `main.c` - 主程序(已添加图形化模式)
- `compile_gui.bat` - 图形化版本编译脚本
### 扩展功能
图形化界面支持进一步扩展:
- 音效支持
- 动画效果
- 主题切换
- 网络对战界面
- AI难度可视化调节
---
**注意**:首次使用图形化界面前,请确保SDL3库已正确配置。
+66 -44
View File
@@ -1,80 +1,102 @@
# 五子棋游戏 Makefile # 五子棋游戏 Makefile
# 支持编译控制台版本和GUI版本 # 支持编译GUI版本 (IUP)
# 编译器设置 # 编译器设置
CC = gcc CC = gcc
CFLAGS = -Wall -Wextra -std=c17 -O2 -Iinclude # 显式指定 Shell 为 PowerShell
LDFLAGS = -lws2_32 SHELL = D:/PowerShell/PowerShell-7.5.4/PowerShell.exe
.SHELLFLAGS = -NoProfile -Command
# SDL3路径设置 CFLAGS = -Wall -Wextra -std=c17 -O2 -Iinclude -finput-charset=UTF-8 -fexec-charset=UTF-8
SDL3_PATH = D:/settings/SDL/SDL3-3.2.22/x86_64-w64-mingw32 # ENet 包含路径
SDL3_INCLUDE = -I$(SDL3_PATH)/include ENET_INC = -Ilibs/enet/include
SDL3_LIBS = -L$(SDL3_PATH)/lib -lSDL3 -lmingw32 CFLAGS += $(ENET_INC)
LDFLAGS = -lws2_32 -lwinmm
# IUP路径设置
IUP_PATH = libs/iup-3.31_Win64_dllw6_lib
IUP_INCLUDE = "-I$(IUP_PATH)/include"
# IUP链接库: iup, gdi32, comdlg32, comctl32, uuid, ole32
IUP_LIBS = "-L$(IUP_PATH)" -liup -lgdi32 -lcomdlg32 -lcomctl32 -luuid -lole32
# 目录设置
SRC_DIR = src
OBJ_DIR = obj
BIN_DIR = bin
# 源文件 # 源文件
COMMON_SOURCES = src/main.c src/gobang.c src/ai.c src/config.c src/game_mode.c src/globals.c \ COMMON_SOURCES = $(SRC_DIR)/gobang.c $(SRC_DIR)/ai.c $(SRC_DIR)/config.c \
src/init_board.c src/network.c src/record.c src/ui.c src/gui.c $(SRC_DIR)/globals.c \
$(SRC_DIR)/network.c $(SRC_DIR)/record.c \
$(SRC_DIR)/gui_core.c $(SRC_DIR)/gui_draw.c \
$(SRC_DIR)/gui_game.c $(SRC_DIR)/gui_replay.c \
$(SRC_DIR)/gui_menu.c
GUI_SOURCES = $(COMMON_SOURCES) # ENet 源文件
CONSOLE_SOURCES = $(COMMON_SOURCES) ENET_SOURCES = libs/enet/callbacks.c libs/enet/compress.c libs/enet/host.c \
libs/enet/list.c libs/enet/packet.c libs/enet/peer.c \
libs/enet/protocol.c libs/enet/win32.c
# 目标文件 # 目标文件 (src/xxx.c -> obj/xxx.o)
COMMON_OBJECTS = $(patsubst src/%.c,src/%.o,$(filter %.c,$(COMMON_SOURCES))) COMMON_OBJECTS = $(patsubst $(SRC_DIR)/%.c,$(OBJ_DIR)/%.o,$(COMMON_SOURCES))
ENET_OBJECTS = $(patsubst libs/enet/%.c,$(OBJ_DIR)/enet_%.o,$(ENET_SOURCES))
# 可执行文件 # 可执行文件
CONSOLE_TARGET = gobang_console.exe GUI_TARGET = $(BIN_DIR)/gobang_gui.exe
GUI_TARGET = gobang_gui.exe
# 默认目标 # 默认目标
all: $(CONSOLE_TARGET) $(GUI_TARGET) all: directories $(GUI_TARGET)
# 控制台版本 # 创建目录 (PowerShell 语法)
$(CONSOLE_TARGET): $(COMMON_OBJECTS) directories:
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -o $@ $^ $(SDL3_LIBS) $(LDFLAGS) if (!(Test-Path "$(OBJ_DIR)")) { New-Item -ItemType Directory -Path "$(OBJ_DIR)" | Out-Null }
if (!(Test-Path "$(BIN_DIR)")) { New-Item -ItemType Directory -Path "$(BIN_DIR)" | Out-Null }
# GUI版本 # GUI版本
$(GUI_TARGET): $(COMMON_OBJECTS) $(GUI_TARGET): $(COMMON_OBJECTS) $(ENET_OBJECTS) $(OBJ_DIR)/main.o
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -o $@ $^ $(SDL3_LIBS) $(LDFLAGS) $(CC) $(CFLAGS) $(IUP_INCLUDE) -o $@ $^ $(IUP_LIBS) $(LDFLAGS)
Copy-Item -Path "$(subst /,\,$(IUP_PATH))\iup.dll" -Destination "$(BIN_DIR)" -Force
# 通用目标文件编译规则(包含SDL3头文件路径,因为多个文件包含gui.h) # 通用目标文件编译规则
src/%.o: src/%.c $(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(CC) $(CFLAGS) $(SDL3_INCLUDE) -c -o $@ $< $(CC) $(CFLAGS) $(IUP_INCLUDE) -c -o $@ $<
# 清理规则 # 编译 ENet 源文件
$(OBJ_DIR)/enet_%.o: libs/enet/%.c | directories
$(CC) $(CFLAGS) $(ENET_INC) -c -o $@ $<
# 编译 main.c
$(OBJ_DIR)/main.o: $(SRC_DIR)/main.c
$(CC) $(CFLAGS) $(IUP_INCLUDE) -c -o $@ $<
# 清理规则 (PowerShell 语法)
clean: clean:
del /Q src\*.o *.exe 2>nul || true if (Test-Path "$(OBJ_DIR)") { Remove-Item -Path "$(OBJ_DIR)" -Recurse -Force }
if (Test-Path "$(BIN_DIR)") { Remove-Item -Path "$(BIN_DIR)" -Recurse -Force }
# 编译控制台版本 # 编译GUI版本
console: $(CONSOLE_TARGET) gui: directories $(GUI_TARGET)
# 只编译GUI版本
gui: $(GUI_TARGET)
# 安装规则(可选) # 安装规则(可选)
install: all install: all
@echo Installing executables... Write-Host "Installing executables..."
copy $(CONSOLE_TARGET) C:\Program Files\Gobang\ 2>nul || echo Install directory not found Copy-Item -Path "$(GUI_TARGET)" -Destination "C:\Program Files\Gobang\" -Force
copy $(GUI_TARGET) C:\Program Files\Gobang\ 2>nul || echo Install directory not found
# 运行控制台版本
run-console: $(CONSOLE_TARGET)
.\$(CONSOLE_TARGET)
# 运行GUI版本 # 运行GUI版本
run-gui: $(GUI_TARGET) run-gui: $(GUI_TARGET)
.\$(GUI_TARGET) & ".\$(GUI_TARGET)"
# 帮助信息 # 帮助信息
help: help:
@echo Available targets: @echo Available targets:
@echo all - Build both console and GUI versions @echo all - Build GUI version
@echo console - Build console version only @echo gui - Build GUI version
@echo gui - Build GUI version only
@echo clean - Remove all object files and executables @echo clean - Remove all object files and executables
@echo run-console - Build and run console version
@echo run-gui - Build and run GUI version @echo run-gui - Build and run GUI version
@echo install - Install executables to system directory @echo install - Install executables to system directory
@echo help - Show this help message @echo help - Show this help message
# 声明伪目标 # 声明伪目标
.PHONY: all clean console gui install run-console run-gui help .PHONY: all clean gui install run-gui help directories
+95 -284
View File
@@ -1,346 +1,157 @@
# C语言五子棋人机对战AI # C语言五子棋系统
![Build Status](https://img.shields.io/badge/build-passing-brightgreen) ![Build Status](https://img.shields.io/badge/build-passing-brightgreen)
![License](https://img.shields.io/badge/license-MIT-blue) ![License](https://img.shields.io/badge/license-MIT-blue)
![Version](https://img.shields.io/badge/version-v8.2-blue) ![Version](https://img.shields.io/badge/version-v9.0-blue)
![Platform](https://img.shields.io/badge/platform-Windows-lightgrey) ![Platform](https://img.shields.io/badge/platform-Windows-lightgrey)
> 🎯 **最新版本 v8.2** - 编译脚本优化更新,完善批处理脚本功能、增强用户编译体验、优化开发工作流程 > 🎯 **最新版本 v9.0** - 全面集成 ENet 网络联机功能,重构 GUI 代码架构,纯图形化交互体验。
## 📋 大版本更新 ## 📋 大版本更新
### v8.2 (2025-01-20) - 编译脚本优化更新 ### v9.0 (2026-03-17) - 局域网联机与 GUI 架构重构
- 🔧 **交互式编译脚本** - compile_gui.bat支持选择编译控制台或GUI版本
- 📋 **用户友好界面** - 提供清晰的编译选项菜单和操作指引 - 🌐 **局域网对战** - 引入 ENet 库,支持稳定、无粘包的局域网多人对战(创建房间/加入房间)。
- **编译流程优化** - 统一编译参数,解决SDL3依赖问题 - 🎨 **GUI 深度重构** - 拆分臃肿的 GUI 代码,模块化为 `gui_core`, `gui_game`, `gui_menu`, `gui_draw`, `gui_replay`,大幅提升可维护性。
- 🌐 **多语言支持** - 英文界面避免编码问题,确保兼容性 - 📦 **精简安装包** - 优化 Inno Setup 打包脚本,实现极简核心依赖打包。
- 📦 **安装包制作** - 提供Inno Setup和NSIS两种安装包方案 - **全面摒弃控制台** - 专注于基于 IUP 的原生图形化交互体验。
-**错误处理完善** - 添加无效输入处理和详细错误提示
- 🎯 **开发体验提升** - 简化编译流程,提高开发效率 ---
## 目录 ## 目录
- [C语言五子棋人机对战AI](#c语言五子棋人机对战ai)
- [C语言五子棋系统](#c语言五子棋系统)
- [📋 大版本更新](#-大版本更新) - [📋 大版本更新](#-大版本更新)
- [v8.2 (2025-01-20) - 编译脚本优化更新](#v82-2025-01-20---编译脚本优化更新) - [v9.0 (2026-03-17) - 局域网联机与 GUI 架构重构](#v90-2026-03-17---局域网联机与-gui-架构重构)
- [目录](#目录) - [目录](#目录)
- [项目简介](#项目简介) - [项目简介](#项目简介)
- [功能特性](#功能特性) - [功能特性](#功能特性)
- [🎮 游戏模式](#-游戏模式) - [🎮 游戏模式](#-游戏模式)
- [⚙️ 游戏设置](#-游戏设置) - [⚙️ 核心功能](#-核心功能)
- [🎯 游戏功能](#-游戏功能)
- [💻 用户体验](#-用户体验)
- [🔧 技术特性](#-技术特性)
- [快速开始](#快速开始) - [快速开始](#快速开始)
- [编译项目](#编译项目) - [编译项目](#编译项目)
- [控制台版本编译](#控制台版本编译) - [打包安装程序](#打包安装程序)
- [GUI版本编译(需要SDL3](#gui版本编译需要sdl3)
- [运行游戏](#运行游戏)
- [控制台版本](#控制台版本)
- [GUI版本](#gui版本)
- [游戏玩法](#游戏玩法) - [游戏玩法](#游戏玩法)
- [🚀 快速开始](#-快速开始) - [技术架构](#技术架构)
- [🎯 对局操作](#-对局操作) - [AI 算法](#ai-算法)
- [⚙️ 配置管理](#-配置管理) - [网络通信](#网络通信)
- [📊 复盘功能](#-复盘功能) - [图形界面](#图形界面)
- [🌐 网络对战功能](#-网络对战功能)
- [环境要求](#环境要求)
- [常见问题](#常见问题)
- [权限问题](#权限问题)
- [乱码显示问题](#乱码显示问题)
- [AI 设计实现](#ai-设计实现)
- [核心算法](#核心算法)
- [棋局评估函数](#棋局评估函数)
- [项目结构](#项目结构) - [项目结构](#项目结构)
- [📁 核心模块](#-核心模块)
- [🎮 功能模块](#-功能模块)
- [📄 配置和文档](#-配置和文档)
- [🔧 开发工具](#-开发工具)
- [许可证](#许可证) - [许可证](#许可证)
- [欢迎贡献](#欢迎贡献)
- [未来计划](#未来计划) ---
- [✅ 已完成功能](#-已完成功能)
- [🚀 开发路线图](#-开发路线图)
- [📱 用户体验提升](#-用户体验提升)
- [🌐 网络功能](#-网络功能)
- [🧠 AI增强](#-ai增强)
- [🔧 技术优化](#-技术优化)
## 项目简介 ## 项目简介
这是一个使用C语言实现的现代化五子棋对战系统,支持人机对战、双人对战和网络对战三种模式。系统基于 Alpha-Beta 剪枝优化的 Minimax 算法,具备完整的配置管理、复盘分析、智能评分和网络通信功能。v8.0版本新增SDL3图形化界面,提供现代化的可视化游戏体验,同时保持控制台版本的完整功能。
这是一个使用纯 C 语言编写的现代化五子棋系统。采用轻量级的 IUP 库构建原生风格的图形化用户界面。系统不仅支持基于 Minimax 算法(带 Alpha-Beta 剪枝)的高级人机对战,还完美支持基于 ENet 的局域网多人实时联机对弈。
## 功能特性 ## 功能特性
### 🎮 游戏模式 ### 🎮 游戏模式
- **人机对战模式** - 与智能AI进行对弈
- **双人对战模式** - 支持本地双人游戏
- **复盘模式** - 回顾和分析历史对局
- **GUI图形化模式** - 现代化图形界面游戏体验
- **控制台模式** - 传统终端界面游戏模式
### ⚙️ 游戏设置 - **人机对战 (PvE)** - 挑战 1-5 级难度的智能 AI。
- **自定义棋盘尺寸** - 支持5x5至25x25可调节棋盘 - **局域网联机 (Network)** - 建立主机或作为客机加入,与朋友在局域网内实时对战。
- **多级AI难度** - 1-5级智能难度可选 - **复盘模式 (Replay)** - 载入自动保存的对局记录(CSV),逐步回放并分析对局。
- **配置管理系统** - 持久化保存游戏设置
- **禁手规则支持** - 可选启用五子棋标准禁手规则
- **回合计时器** - 可设置每回合思考时间限制
### 🎯 游戏功能 ### ⚙️ 核心功能
- **实时对局控制** - 悔棋、认输、保存等操作
- **自动游戏记录** - 完整保存对局过程到CSV文件
- **智能评分系统** - 对每步棋进行专业评分和分析
- **完整复盘功能** - 逐步回放对局并显示评分
- **MVP评选系统** - 自动评选对局最佳表现者
### 💻 用户体验 - **实时对局控制** - 支持悔棋(PvE)、断线重连检测、胜负判定。
- **双界面支持** - 同时提供图形化界面和终端界面 - **自动游戏记录** - 每局游戏结束后自动保存至 `bin/records/` 目录。
- **SDL3图形化界面** - 现代化的可视化游戏体验 - **模块化构建** - 提供高度配置化的 Makefile,一键源码编译包含 ENet 和主程序的二进制文件。
- **鼠标操作支持** - 直观的点击落子操作
- **完备输入验证** - 确保所有用户输入的有效性和安全性
- **智能错误提示** - 详细的错误信息和操作指导
- **响应式设计** - 自适应窗口大小和分辨率
- **跨平台兼容** - 支持Windows系统,预留跨平台扩展
### 🔧 技术特性 ---
- **模块化架构** - 清晰的代码结构,便于维护和扩展
- **SDL3图形库集成** - 现代化的跨平台图形渲染支持
- **双版本架构** - 控制台版本和GUI版本并行开发
- **结构体定义集中化** - 所有数据结构统一在type.h中管理
- **配置参数统一管理** - 所有配置宏定义集中在config.h中
- **全局变量统一管理** - 所有全局变量集中在globals模块中管理
- **内存优化管理** - 高效的内存使用和资源管理
- **配置文件支持** - INI格式配置文件自动加载保存
- **UTF-8编码支持** - 完美支持中文显示
- **事件驱动架构** - 高效的图形界面事件处理机制
- **安装包支持** - 提供专业的软件安装和分发方案
- **网络对战功能** - 完整的在线多人对战系统
## 快速开始 ## 快速开始
### 编译项目 ### 编译项目
#### 控制台版本编译 项目使用 Makefile 进行构建,依赖 MinGW-w64 工具链。
在项目根目录下打开 PowerShell 或 CMD,运行:
```bash ```bash
gcc -std=c17 -o gobang.exe *.c -lws2_32 # 清理旧文件
mingw32-make clean
# 编译生成 GUI 可执行文件
mingw32-make gui
``` ```
或者使用优化编译: 生成的可执行文件 `gobang_gui.exe` 和所需的动态链接库 `iup.dll` 会输出到 `bin/` 目录下。
**运行游戏:**
```bash ```bash
gcc -O2 -o gobang.exe main.c gobang.c game_mode.c ai.c record.c init_board.c ui.c config.c globals.c network.c -lws2_32 .\bin\gobang_gui.exe
``` ```
#### GUI版本编译(需要SDL3 ### 打包安装程序
```bash
gcc -std=c17 -o gobang_gui.exe *.c -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32 如果你需要将游戏打包成 Windows 安装程序,项目提供了 Inno Setup 脚本。
copy "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\bin\SDL3.dll" . 确保你已安装 [Inno Setup 6](https://jrsoftware.org/isinfo.php),然后运行:
```powershell
& "D:\Program Files (x86)\Inno Setup 6\iscc.exe" installer\installer.iss
``` ```
或者使用批处理文件: 生成的安装包 `Gobang_Inno_Setup.exe` 将存放在 `installer\dist\` 目录下。
```bash
.\compile_gui.bat
```
**注意:** ---
- Windows系统需要添加 `-lws2_32` 链接库以支持网络功能
- GUI版本需要SDL3库支持,请确保SDL3路径正确
- 编译GUI版本后需要将SDL3.dll复制到可执行文件目录
### 运行游戏
#### 控制台版本
```bash
.\gobang.exe
```
#### GUI版本
```bash
.\gobang_gui.exe
```
## 游戏玩法 ## 游戏玩法
### 🚀 快速开始 1. 运行 `gobang_gui.exe` 启动游戏主菜单。
1. **启动游戏**:运行 `gobang.exe` 进入主菜单 2. 选择你要进行的游戏模式:
2. **选择模式** - **人机对战**:直接进入游戏,玩家执黑先行,点击棋盘空白处落子。
- `1` - **人机对战模式** - 与AI智能对手进行五子棋对战 - **局域网联机**
- `2` - **双人对战模式** - 两名玩家轮流对弈的本地对战 - **作为房主**:点击“局域网联机” -> “创建房间”,等待好友加入(默认端口8888)。
- `3` - **网络对战模式** - 通过网络与远程玩家实时对战 - **作为玩家**:点击“局域网联机” -> 输入房主的 IP 地址和端口 -> “加入房间”。
- `4` - **复盘模式** - 回放历史对局并查看详细分析 - **复盘模式**:选择历史对局记录,使用“上一步/下一步”按钮进行回放。
- `5` - **配置管理** - 自定义游戏设置和参数调整
- `6` - **游戏规则** - 查看五子棋游戏规则和操作说明
- `7` - **关于信息** - 查看项目版本和开发者信息
- `0` - **退出游戏** - 安全退出程序
### 🎯 对局操作 ---
- **落子**:输入坐标 (格式: `行 列`,如 `8 8`)
- **悔棋**:输入 `R``r` 撤销上一步
- **认输**:输入 `S``s` 主动认输
- **保存**:输入 `SAVE` 保存当前对局
- **退出**:输入 `EXIT` 退出当前对局
### ⚙️ 配置管理 ## 技术架构
- **棋盘大小**5x5 至 25x25 可调 (默认15x15)
- **AI难度**1-5级智能难度 (默认3级)
- **禁手规则**:可选启用标准五子棋禁手
- **计时器**:可设置每回合时间限制
- **配置保存**:所有设置自动保存到 `gobang_config.ini`
### 📊 复盘功能 ### AI 算法
- **自动记录**:每局游戏自动保存到 `records/` 目录
- **逐步回放**:按步骤重现整局对弈过程
- **评分分析**:显示每步棋的专业评分
- **MVP评选**:自动评选本局最佳表现者
- **胜负统计**:完整的对局结果记录
### 🌐 网络对战功能 - **Minimax 博弈树**:遍历所有可能的落子情况。
- **服务器模式**:创建游戏房间等待其他玩家加入 - **Alpha-Beta 剪枝**:极大提升搜索效率,AI 默认思考深度为 3 层。
- **客户端模式**:连接到指定服务器进行对战 - **启发式评估函数**:基于连五、活四、冲四、活三等经典五子棋棋型进行棋局评分。
- **实时同步**:棋盘状态和游戏进度实时同步
- **连接管理**:自动处理网络连接和断线重连
- **延迟显示**:实时显示网络延迟状态
- **安全验证**:基本的数据验证和防作弊检测
## 环境要求 ### 网络通信
- 操作系统: Windows (当前版本使用了Windows特有的 `_kbhit()``Sleep()` 函数,因此暂不跨平台)
- 编译器: GCC (MinGW-w64)
- 终端: 支持UTF-8编码的终端
> **跨平台兼容性说明:** - **底层库**[ENet](http://enet.bespin.org/) (基于 UDP 的可靠网络传输协议)。
> - **机制**:游戏采用非阻塞轮询机制处理网络事件,完美解决传统 TCP 粘包问题,确保落子坐标、断开连接等指令 100% 可靠送达。
> 为了未来在Linux或macOS等其他操作系统上运行,需要将平台特定的代码(如 `_kbhit()`)替换为跨平台的实现,或使用条件编译(`#ifdef _WIN32`)进行隔离。
## 常见问题 ### 图形界面
### 权限问题 - **底层库**[IUP](https://www.tecgraf.puc-rio.br/iup/) (轻量级、跨平台的 C 语言原生 GUI 库)。
如果在保存游戏记录时提示“无法创建文件”,这通常是由于程序缺少写入权限。请尝试以下解决方案: - **机制**:事件驱动架构,通过回调函数响应用户的鼠标点击、按钮触发和窗口切换。
1. **以管理员身份运行**:右键点击 `gobang.exe` 并在管理员权限的终端中运行程序。 ---
2. **更改项目目录权限**:确保项目目录不在受系统保护的目录(如 `C:\Program Files`),建议将项目放在用户目录下,例如 `D:\Code`
3. **手动创建 `records` 目录**:如果 `records` 目录不存在,请在 `gobang.exe` 所在目录手动创建一个。
### 乱码显示问题
如果在Windows终端中出现中文字符显示为乱码,这是由于终端代码页不匹配导致的。请在程序运行前执行以下命令:
```bash
chcp 65001
```
这会把当前终端的代码页切换为UTF-8,从而正确显示中文字符。为了方便,你可以创建一个批处理文件 `.bat` 来自动执行此操作。
**start_game.bat**
```batch
@echo off
chcp 65001
.\gobang.exe
```
## AI 设计实现
项目的AI主要基于以下技术实现:
### 核心算法
- **Minimax算法 (Minimax)**:作为博弈树的基础模型,为双人对弈的每一步选择最优解法。
- **Alpha-Beta 剪枝 (Alpha-Beta Pruning)**:对Minimax算法的重大优化,通过剪掉那些不影响最终决策的树枝来提高AI的计算效率,使其能够在有限时间内达到更深的搜索深度。
- **搜索深度**:AI的思考深度,默认为3层,可以根据难度等级进行调整。深度越大,AI预测能力越强,但计算耗时也越长。
### 棋局评估函数
为了对棋局进行价值评估,AI使用了一套复杂的评分系统,其主要依据包括:
- **棋型识别 (Pattern Recognition)**:能够识别并评估游戏中的关键棋型,如“连五”、“活四”、“冲四”、“活三”等,并为每种棋型赋予不同权重。
- **位置权重 (Positional Value)**:棋盘上不同位置的战略价值不同,中心位置通常比边缘位置更有优势。评估函数会为棋盘上的落子点附加位置分。
- **威胁检测 (Threat Detection)**:评估那些能够直接形成制胜局面的落子点,如“四三”或“活三”,并对这些点给予极高的评价值,以抓住制胜机会。
- **双向连通性**:在评估一个点时,会同时判断其是否拥有足够的空间形成有效棋型,避免在被封锁的位置下出无效棋。
## 项目结构 ## 项目结构
### 📁 核心模块 ```text
- **`main.c`** - 主程序入口,负责初始化与游戏模式选择 Gobang/
- **`gobang.c/h`** - 核心游戏逻辑,包括棋盘操作、胜负判断 ├── bin/ # 编译输出目录 (包含 exe, dll 和 records)
- **`game_mode.c/h`** - 游戏模式实现 (人机对战、双人对战、复盘模式) ├── include/ # 头文件目录
- **`ai.c/h`** - AI算法实现 (Minimax + Alpha-Beta剪枝) ├── libs/ # 第三方库源码及预编译库 (ENet, IUP)
- **`gui.c/h`** - SDL3图形化界面模块 (窗口管理、事件处理、图形渲染) ├── src/ # 核心源代码
│ ├── main.c # 程序入口
### 🎮 功能模块 │ ├── gobang.c # 五子棋核心规则与逻辑
- **`ui.c/h`** - 用户界面模块,负责所有显示和交互 │ ├── ai.c # 智能 AI 算法
- **`record.c/h`** - 游戏记录系统 (保存、加载、复盘、评分) │ ├── network.c # ENet 网络通信封装
- **`init_board.c/h`** - 棋盘初始化和游戏设置 │ ├── record.c # 棋谱记录与解析
- **`config.c/h`** - 配置管理系统 (参数设置、文件读写) │ ├── gui_core.c # GUI 初始化与核心循环
- **`globals.c/h`** - 全局变量统一管理模块 │ ├── gui_game.c # 游戏主界面与交互逻辑
- **`network.c/h`** - 网络功能模块 (为未来网络对战预留) │ ├── gui_menu.c # 游戏主菜单界面
│ ├── gui_draw.c # 棋盘与棋子渲染
### 📄 配置和文档 │ └── gui_replay.c # 复盘模式交互逻辑
- **`gobang_config.ini`** - 游戏配置文件 (自动生成和保存) ├── installer/ # Inno Setup 安装包打包脚本及输出
- **`records/`** - 对局记录目录 (CSV格式存储) ├── Makefile # 自动化构建脚本
- **`type.h`** - 数据结构和类型定义集中文件 └── README.md # 项目说明文档
- **`compile_gui.bat`** - GUI版本编译脚本 ```
- **`installer/`** - 安装包制作目录
- **`setup.iss`** - Inno Setup安装脚本
- **`installer.nsi`** - NSIS安装脚本
- **`MD/README.md`** - 项目说明文档
- **`MD/README_GUI.md`** - GUI版本使用指南
- **`MD/AI_Enhancement_Guide.md`** - AI算法增强指南
- **`MD/NETWORK_README.md`** - 网络功能使用说明
- **`MD/Architecture_Refactoring_Guide.md`** - 代码架构重构详细指南
### 🔧 开发工具
- **`.vscode/`** - VS Code 配置文件
- **`.idea/`** - IntelliJ IDEA 配置文件
- **`.vs/`** - Visual Studio 配置文件
## 许可证 ## 许可证
本项目采用 [MIT 许可证](https://opensource.org/licenses/MIT)授权。 本项目采用 [MIT 许可证](https://opensource.org/licenses/MIT)授权。欢迎自由修改和分发!
这意味着你可以自由地使用、复制、修改、合并、出版、分发、再授权和/或销售本软件的副本,只需在所有副本或重要部分中包含原始的版权声明和本许可声明即可。
## 欢迎贡献
我们非常欢迎任何形式的反馈和贡献!如果你发现了Bug、有功能建议,或希望改进代码,请随时通过以下方式参与:
- **提交 Issue**:对于问题反馈或新想法,请在 [GitHub Issues](https://github.com/LHY0125/Gobang-Game/issues) 页面提交详细描述。
- **发起 Pull Request**:如果你对源码进行了改进,欢迎提交 Pull Request。请确保你的代码风格与项目保持一致,并提供清晰的改动说明。
你的每一次贡献都将使这个项目变得更好!
## 未来计划
### ✅ 已完成功能
- [x] **SDL3图形化界面** - 完成现代化GUI界面开发,支持可视化棋盘操作
- [x] **双版本架构** - 实现控制台版本和GUI版本并行支持
- [x] **安装包制作** - 提供Inno Setup和NSIS两种专业安装包方案
- [x] **鼠标交互支持** - 实现直观的点击落子和界面操作
- [x] **窗口管理优化** - 完善的窗口显示、居中和事件处理机制
- [x] **模块化架构设计** - 完成代码重构,实现清晰的模块分离
- [x] **全局变量统一管理** - 所有全局变量集中在globals模块中管理
- [x] **宏定义优化** - 消除重复定义,统一管理所有宏定义
- [x] **配置管理系统** - 实现INI配置文件的自动加载和保存
- [x] **完整复盘功能** - 支持对局记录、回放和专业评分分析
- [x] **用户界面优化** - 实现现代化的终端UI界面
- [x] **智能评分系统** - 完成每步棋的评分和MVP评选功能
- [x] **禁手规则支持** - 添加标准五子棋禁手规则选项
- [x] **网络模块预留** - 为未来网络对战功能预留完整接口
### 🚀 开发路线图
#### 📱 用户体验提升
- [x] **图形用户界面 (GUI)**:使用 `SDL3` 开发现代化图形界面
- [ ] **主题系统**:支持多种UI主题和棋盘样式
- [ ] **音效系统**:添加落子音效和背景音乐
- [ ] **动画效果**:添加落子动画和界面过渡效果
- [ ] **多语言支持**:支持中英文界面切换
#### 🌐 网络功能
- [ ] **在线对战模式**:实现网络多人对战功能
- [ ] **排行榜系统**:在线玩家等级和排名系统
- [ ] **观战功能**:支持观看其他玩家对局
#### 🧠 AI增强
- [ ] **开局库系统**:集成专业开局棋谱数据库
- [ ] **神经网络AI**:基于深度学习的高级AI对手
- [ ] **AI训练模式**:允许AI通过对局学习和改进
#### 🔧 技术优化
- [ ] **跨平台支持**:完整支持Linux和macOS系统
- [ ] **性能优化**:多线程搜索和内存优化
- [ ] **数据库支持**:使用SQLite存储对局历史和统计
-193
View File
@@ -1,193 +0,0 @@
五子棋对战系统 - 代码统计报告
========================================
项目名称:五子棋多模式对战系统
统计时间:2025年10月8日
项目版本:v8.2
开发语言:C语言 + SDL3图形库
GitHub仓库:https://github.com/LHY0125/Gobang-Game.git
========================================
📊 代码行数统计
========================================
【C源文件 (.c)】
├── main.c 85行
├── gobang.c 269行
├── game_mode.c 917行
├── ai.c 589行
├── record.c 531行
├── init_board.c 118行
├── ui.c 204行
├── config.c 331行
├── network.c 426行
├── globals.c 37行
└── gui.c 450行 (v8.0新增)
【头文件 (.h)】
├── gobang.h 101行
├── game_mode.h 99行
├── ai.h 39行
├── record.h 45行
├── init_board.h 35行
├── ui.h 62行
├── config.h 170行
├── network.h 186行
├── globals.h 41行
├── type.h 93行
└── gui.h 85行 (v8.0新增)
========================================
📈 总计统计
========================================
总代码行数:4,933行 (v8.0新增535行)
文件类型分布:
• C源文件:3,977行 (80.6%)
• 头文件:956行 (19.4%)
v8.0版本新增:
• GUI图形界面模块:535行 (10.8%)
• 安装包配置文件:2个
• 编译脚本文件:1个
模块代码分布:
• 游戏模式模块:917行 (18.6%)
• AI智能模块:589行 (11.9%)
• GUI图形界面模块:535行 (10.8%) (v8.0新增)
• 记录系统模块:531行 (12.1%)
• 网络对战模块:426行 (9.7%)
• 配置管理模块:331行 (7.5%)
• 核心游戏模块:269行 (6.1%)
• 用户界面模块:204行 (4.6%)
• 配置参数模块:170行 (3.9%)
• 棋盘初始化模块:118行 (2.7%)
• 类型定义模块:93行 (2.1%)
• 主程序模块:84行 (1.9%)
• 全局变量模块:41行 (0.9%)
========================================
💬 注释统计
========================================
【注释统计】
总注释行数:1,248行
注释覆盖率:30.1%
注释类型分布:
• 函数说明注释:498行 (39.9%)
• 代码逻辑注释:425行 (34.1%)
• 文件头注释:325行 (26.0%)
注释质量分析:
• 文件头注释:每个文件都有详细的文档头
• 函数注释:使用Doxygen格式的完整函数文档
• 行内注释:关键逻辑的解释说明
• 分块注释:代码段落的功能说明
估算注释字数:约8,500-10,000字
注释内容包括:
• 详细的函数参数和返回值说明
• 算法逻辑的中文解释
• 代码块的功能描述
• 重要变量和常量的用途说明
• 网络协议和数据结构的详细文档
========================================
🏆 代码质量评价
========================================
【优秀特点】
✓ 注释覆盖率高:几乎每个函数都有详细文档
✓ 代码结构清晰:模块化设计,职责分离明确
✓ 命名规范:变量和函数名具有良好的可读性
✓ 文档完整:包含完整的API文档和使用说明
✓ 架构合理:网络模块、AI模块、UI模块分离
✓ 跨平台支持:Windows和Linux双平台兼容
【技术亮点】
• SDL3图形化界面实现(v8.0新增)
• 双版本架构设计(控制台+GUI)(v8.0新增)
• 鼠标交互和事件驱动架构(v8.0新增)
• 专业安装包制作支持(v8.2新增)
• Inno Setup和NSIS双重打包方案(v8.2新增)
• 完整的软件分发体系(v8.2新增)
• 完整的网络对战功能实现
• 智能AI算法与评估系统
• 灵活的配置管理系统
• 详细的游戏记录与复盘功能
• 规范的禁手规则实现
• 实时计时器系统
• 全局变量统一管理
• 跨平台网络通信支持
• 代码架构模块化重构
• 配置参数集中化管理
• 类型定义标准化
【总体评价】
这是一个非常优秀的C语言项目,代码量适中但功能完整,
注释详尽,体现了良好的编程习惯和专业素养!
项目从单一的五子棋游戏发展为支持多种对战模式的完整系统,
包括人机对战、双人对战和网络对战,功能丰富,架构清晰,
是C语言项目开发的优秀范例。
v8.2版本进一步完善了软件分发体系,
通过Inno Setup和NSIS双重安装包方案,
实现了专业级的软件打包和部署功能,
为用户提供了便捷的一键安装体验,
标志着项目从开发阶段向产品化阶段的重要转变。
v8.0版本的图形化界面是项目发展的重大突破,
通过SDL3图形库实现了现代化的可视化界面,
支持鼠标交互操作,大幅提升了用户体验。
双版本架构设计既保持了控制台版本的轻量特性,
又提供了GUI版本的现代化体验,满足不同用户需求。
网络对战功能的加入使得项目具备了现代化游戏的特征,
支持实时在线对战,为用户提供了更丰富的游戏体验。
v7.0版本的代码架构重构是项目发展的重要里程碑,
通过配置统一管理、全局变量规范化、类型定义标准化等措施,
大幅提升了代码的可维护性和扩展性,为v8.0的GUI功能
奠定了坚实的架构基础。
========================================
📋 项目文件结构
========================================
核心模块:
• main.c/gobang.c - 主程序和核心游戏逻辑
• game_mode.c/h - 游戏模式管理(人机/双人/网络)
• ai.c/h - AI智能算法实现
• gui.c/h - SDL3图形化界面模块(v8.0新增)
• network.c/h - 网络对战功能
• record.c/h - 游戏记录与复盘
• ui.c/h - 用户界面管理
• config.c/h - 配置文件管理
• init_board.c/h - 棋盘初始化
• globals.c/h - 全局变量统一管理
• type.h - 数据结构和类型定义集中文件(v7.0新增)
配置文件:
• gobang_config.ini - 游戏配置文件
• compile_gui.bat - GUI版本编译脚本(v8.0新增)
安装包目录:
• installer/ - 安装包制作目录(v8.0新增)
• setup.iss - Inno Setup安装脚本
• installer.nsi - NSIS安装脚本
文档目录:
• MD/ - 项目文档目录
• README_GUI.md - GUI版本使用指南(v8.0新增)
• TXT/ - 文本文档目录
• records/ - 游戏记录存储目录
开发环境:
• .vscode/ - VS Code配置
• .idea/ - IntelliJ IDEA配置
========================================
-103
View File
@@ -1,103 +0,0 @@
/**
* @file 五子棋对战系统
* @brief C语言五子棋多模式对战系统
* @details 支持人机对战、双人对战、网络对战的完整五子棋游戏系统,v8.0新增SDL3图形化界面
* @author 刘航宇(3364451258@qq.com、15236416560@163.com、lhy3364451258@outlook.com)
* @date 2025-10-8
* @version 8.2
* @note
* 1. v8.2专业安装包:
* - 📦 双重打包方案:支持Inno Setup和NSIS两种安装包制作
* - 🚀 一键安装部署:完整的软件分发解决方案
* - 🔧 安装程序优化:自动创建快捷方式和注册表项
* - 🗂️ 完整文件打包:包含所有源码、文档和依赖文件
* - 🔄 完整卸载功能:支持干净的软件卸载和清理
* - 💼 产品化部署:从开发工具向商业软件的转变
*
* 2. v8.0图形化界面:
* - 🎨 SDL3图形化界面:实现现代化可视化棋盘界面
* - 🖱️ 鼠标交互支持:直观的点击落子操作
* - 🏗️ 双版本架构:控制台版本和GUI版本并行支持
* - 🪟 窗口管理优化:自动居中、响应式设计
* - ⚡ 事件驱动架构:流畅的用户交互体验
* - 🔧 编译脚本优化:简化GUI版本编译流程
* - 🌐 GUI网络支持:图形化界面支持网络对战
* 2. v7.0架构重构:
* - 🏗️ 代码架构全面重构,实现模块化设计
* - 📋 配置参数统一管理,所有配置集中到config.h
* - 🔧 全局变量规范化,统一在globals模块管理
* - 📝 类型定义标准化,集中在type.h中定义
* - 🌐 网络配置重构,从network.h迁移到config.h
* - 🔄 消除重复定义,提高代码一致性
* - 📚 完善文档体系,新增架构重构指南
* 2. v6.1完善功能:
* - 🌐 完善的网络对战模式,支持服务器/客户端架构
* - 🔗 实时数据同步,支持落子、悔棋、认输等网络功能
* - 🛡️ 网络安全验证和连接状态管理
* - 📡 跨平台网络支持(Windows/Linux
* - 🔧 全局变量统一管理,优化代码结构
* - 📋 宏定义统一管理,消除重复定义
* - 🔄 网络协议优化,改进通信稳定性
* 2. 核心游戏功能:
* - 增加了对禁手规则的支持,防止玩家进行无意义的走法。
* - 新增了游戏计时器功能,限制每回合的思考时间。
* - 添加了复盘功能,支持保存和回顾对局记录。
* - 实现了评分系统,可以对每一步棋进行评分和分析。
* 3. 性能优化:
* - 🚀 优化了AI算法,使用Alpha-Beta剪枝提高搜索效率
* - 🎨 改进了棋盘渲染算法,减少了不必要的重绘操作
* - 💾 增加了内存管理优化,避免内存泄漏问题
* - ⚡ 网络通信优化,支持异步消息处理
* - 🔍 智能评分算法优化,提升AI决策质量
* 4. 用户界面改进:
* - 🎮 美化了游戏界面,增加了更多的视觉效果
* - ⌨️ 改进了用户交互体验,增加了快捷键支持
* - 🔊 添加了音效和背景音乐,提升游戏沉浸感
* - 💬 网络对战聊天界面,支持实时交流
* - 📊 游戏状态显示优化,清晰展示连接状态
* 5. 代码结构优化:
* - 🏗️ 重构了代码架构,提高了代码的可读性和可维护性
* - 📝 增加了详细的注释和文档,便于理解和修改
* - 🧩 采用了模块化设计,各功能模块相对独立
* - 🌍 新增网络模块,完整的网络通信架构
* - 🔧 全局状态统一管理,消除代码重复
* - 📋 配置文件标准化,支持灵活配置
* 6. 异常处理:
* - 🛡️ 增加了输入错误的异常处理机制,确保游戏的稳定性
* - 💡 优化了错误提示信息,帮助用户快速定位问题
* - 🔄 增加了程序崩溃恢复功能,提高游戏的可靠性
* - 🌐 网络连接异常处理,自动重连和超时管理
* - 📡 消息传输错误处理,确保数据完整性
* 7. 文档更新:
* - 📚 更新了README文件,提供详细的安装和使用说明
* - 💬 增加了代码注释,提高代码的可读性
* - 👨‍💻 添加了开发者文档,便于后续的功能扩展
* - 🌐 新增网络对战使用指南和配置说明
* - 🔧 API文档完善,支持二次开发
* 8. 版本控制:
* - 📦 使用Git进行版本控制,便于代码管理和协作开发
* - 🚀 建立了清晰的版本发布流程,确保代码质量
* - 🏷️ v7.0版本更新,代码架构全面重构
- 🏷️ v6.1版本更新,网络功能完善优化
* - 📋 完整的变更日志,追踪功能演进
* 9. 测试:
* - ✅ 进行了全面的功能测试,确保各项功能正常运行
* - 🧪 增加了单元测试,提高代码的可靠性
* - ⚡ 进行了性能测试,优化了程序的运行效率
* - 🌐 网络功能压力测试,确保多人对战稳定性
* - 🔒 安全性测试,验证网络通信安全
* - 🔄 协议兼容性测试,确保通信协议稳定
* 10. 开源协议:
* - 📄 选择了MIT开源协议,允许用户自由使用、修改和分发代码
* - 🤝 欢迎社区贡献,共同完善项目
* 11. 贡献者:
* - 👨‍💻 感谢所有为项目做出贡献的开发者和用户
* - 🌟 特别感谢网络功能开发、测试和优化的贡献者
* 12. 联系信息:
* - 📧 如有问题或建议,请联系开发者:
* - 3364451258@qq.com
* - 15236416560@163.com
* - lhy3364451258@outlook.com
* - 🐛 Bug报告和功能建议欢迎通过邮件反馈
* - 💡 网络对战相关问题请详细描述网络环境和连接状态
*/
-69
View File
@@ -1,69 +0,0 @@
项目要求文档 - 五子棋游戏 (v8.2)
1. 项目概述
- 开发一个基于C语言的五子棋游戏,支持本地多人、AI对战和网络对战模式。
- v8.0版本实现双版本架构:支持命令行界面和SDL3图形化界面。
- v8.2版本(当前版本)完善了专业安装包制作体系,提供企业级的软件分发解决方案。
- v8.2版本完善了软件分发体系,支持Inno Setup和NSIS双重安装包制作,提供专业级的软件打包和部署解决方案。
- 包括游戏配置、记录保存、复盘功能和专业安装包。
- 提供现代化的可视化用户体验和传统控制台体验。
2. 功能需求
- **游戏模式**
- 单人模式:玩家 vs AI
- 双人模式:本地两人对战
- 网络模式:通过TCP/IP进行远程对战
- **棋盘和规则**
- 默认15x15棋盘,支持自定义大小(5-25)
- 支持禁手规则选项
- 先手黑子,五连珠获胜
- **AI功能**
- 实现AI算法,支持不同难度级别(1-5级)
- AI应能计算最佳落子位置
- 支持Alpha-Beta剪枝算法和威胁检测
- **配置管理**
- 支持修改棋盘大小、禁手规则、计时器、网络端口等
- 配置保存到INI文件
- 默认配置和重置功能
- 统一的输入验证机制
- **游戏记录**
- 自动保存对局记录到CSV文件
- 支持复盘功能,查看历史对局
- 记录包含时间戳、玩家信息、棋局步骤等
- **用户界面**
- **控制台界面**:传统命令行界面显示棋盘
- **图形化界面**(v8.0新增):基于SDL3的现代化GUI界面
- **鼠标交互**:支持点击落子操作
- **窗口管理**:自动居中、响应式设计
- **事件驱动**:流畅的用户交互体验
- 支持坐标输入落子(数字格式:行 列)
- 显示当前玩家、计时、游戏状态等信息
- 菜单系统和配置界面
- **网络功能**
- 支持服务器/客户端模式
- 实时传输棋子位置
- 超时和断线处理
- 支持端口配置
3. 技术要求
- 使用C语言开发
- Windows平台,包含Winsock网络库(-lws2_32链接)
- **SDL3图形库**v8.0新增):用于GUI界面开发
- **双版本架构**:控制台版本和GUI版本并行支持
- 模块化设计:分离游戏逻辑、AI、配置、网络、UI、GUI等模块
- **安装包制作**:支持Inno Setup专业安装程序
- 错误处理和统一的输入验证
- 支持跨平台编译(Windows/Linux
4. 非功能需求
- 性能:响应时间<1秒(AI计算除外)
- 可维护性:代码模块化,注释清晰
- 兼容性:Windows 11,支持GCC编译器
- 可扩展性:易于添加新的AI算法和游戏模式
5. 交付物
- 源代码文件(.c/.h文件)
- 配置文件(gobang_config.ini
- 记录文件夹(records/
- 文档:README.md、AI增强指南、架构重构指南、网络功能说明、图标指南等
- 代码统计报告和项目简介
Binary file not shown.
BIN
View File
Binary file not shown.
-99
View File
@@ -1,99 +0,0 @@
@echo off
echo ===== Gobang Game Compile Script =====
echo.
echo Please select compile version:
echo 1. Console version (gobang_console.exe)
echo 2. GUI version (gobang_gui.exe)
echo 3. Compile all versions
echo 0. Exit
echo.
set /p choice="Please enter your choice (0-3): "
if "%choice%"=="0" goto :exit
if "%choice%"=="1" goto :console
if "%choice%"=="2" goto :gui
if "%choice%"=="3" goto :all
echo Invalid choice!
pause
exit /b 1
:console
echo.
echo Compiling console version...
echo.
gcc -std=c17 -o gobang_console.exe src/*.c -Iinclude -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
if %ERRORLEVEL% EQU 0 (
echo.
echo Compilation successful! Generated: gobang_console.exe
echo Run command: .\gobang_console.exe
echo.
) else (
echo.
echo Compilation failed! Please check source files and compiler installation
echo.
)
goto :end
:gui
echo.
echo Compiling GUI version...
echo.
REM Check if SDL3 library exists
if not exist "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include" (
echo Error: SDL3 library not found!
echo Please ensure SDL3 is extracted to: D:\settings\SDL\SDL3-3.2.22\
goto :end
)
gcc -std=c17 -o gobang_gui.exe src/*.c -Iinclude -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
if %ERRORLEVEL% EQU 0 (
echo.
echo Compilation successful! Generated: gobang_gui.exe
echo.
echo Copying SDL3.dll to current directory...
copy "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\bin\SDL3.dll" . >nul 2>&1
echo Run command: .\gobang_gui.exe
echo.
) else (
echo.
echo Compilation failed! Please check:
echo 1. SDL3 library path is correct
echo 2. All source files exist
echo 3. gcc compiler is installed
echo.
)
goto :end
:all
echo.
echo Compiling all versions...
echo.
echo [1/2] Compiling console version...
gcc -std=c17 -o gobang_console.exe src/*.c -Iinclude -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
if %ERRORLEVEL% EQU 0 (
echo Console version compilation successful!
) else (
echo Console version compilation failed!
)
echo.
echo [2/2] Compiling GUI version...
if not exist "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include" (
echo Error: SDL3 library not found! Skipping GUI version compilation
goto :end
)
gcc -std=c17 -o gobang_gui.exe src/*.c -Iinclude -ID:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\include -LD:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\lib -lSDL3 -lws2_32
if %ERRORLEVEL% EQU 0 (
echo GUI version compilation successful!
copy "D:\settings\SDL\SDL3-3.2.22\x86_64-w64-mingw32\bin\SDL3.dll" . >nul 2>&1
) else (
echo GUI version compilation failed!
)
echo.
echo Compilation complete! Generated files:
dir *.exe 2>nul
echo.
goto :end
:end
pause
:exit
+3
View File
@@ -16,3 +16,6 @@ NETWORK_PORT=8888
# 网络超时时间 (毫秒) # 网络超时时间 (毫秒)
NETWORK_TIMEOUT=5000 NETWORK_TIMEOUT=5000
# AI难度 (1-5)
AI_DIFFICULTY=3
+4 -36
View File
@@ -34,7 +34,7 @@
//---------- 游戏设置默认值 ----------// //---------- 游戏设置默认值 ----------//
#define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则 #define DEFAULT_USE_FORBIDDEN_MOVES false // 默认不启用禁手规则
#define DEFAULT_USE_TIMER 0 // 默认不启用计时器 #define DEFAULT_USE_TIMER 0 // 默认不启用计时器
#define DEFAULT_TIME_LIMIT 30 // 默认时间限制为30(内部存储) #define DEFAULT_TIME_LIMIT 1800 // 默认时间限制为30分钟(内部以秒存储: 30*60)
//---------- AI参数 ----------// //---------- AI参数 ----------//
#define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度 #define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度
@@ -48,8 +48,6 @@
#define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小 #define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小
// 网络配置 // 网络配置
#define DEFAULT_PORT 8888 // 默认端口(与DEFAULT_NETWORK_PORT保持一致)
#define BUFFER_SIZE 1024 // 缓冲区大小(与NETWORK_BUFFER_SIZE保持一致)
#define MAX_IP_LENGTH 16 // 最大IP地址长度 #define MAX_IP_LENGTH 16 // 最大IP地址长度
// 网络消息类型 // 网络消息类型
@@ -65,7 +63,7 @@
//---------- 评分参数 ----------// //---------- 评分参数 ----------//
// 棋型评分 - 用于calculate_step_score函数 // 棋型评分 - 用于calculate_step_score函数
#define SCORE_FIVE 0 // 五连 #define SCORE_FIVE 5000 // 五连
#define SCORE_LIVE_FOUR 2000 // 活四 #define SCORE_LIVE_FOUR 2000 // 活四
#define SCORE_RUSH_FOUR 1000 // 冲四 #define SCORE_RUSH_FOUR 1000 // 冲四
#define SCORE_DEAD_FOUR 300 // 死四 #define SCORE_DEAD_FOUR 300 // 死四
@@ -118,8 +116,8 @@
//---------- GUI界面参数 ----------// //---------- GUI界面参数 ----------//
// 窗口和棋盘配置 // 窗口和棋盘配置
#define WINDOW_WIDTH 800 #define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 600 #define WINDOW_HEIGHT 800
#define BOARD_OFFSET_X 50 #define BOARD_OFFSET_X 50
#define BOARD_OFFSET_Y 50 #define BOARD_OFFSET_Y 50
#define CELL_SIZE 30 #define CELL_SIZE 30
@@ -153,34 +151,4 @@ void save_game_config();
*/ */
void reset_to_default_config(); void reset_to_default_config();
/**
* @brief 显示当前配置
*/
void display_current_config();
/**
* @brief 配置棋盘大小
*/
void config_board_size();
/**
* @brief 配置禁手规则
*/
void config_forbidden_moves();
/**
* @brief 配置计时器
*/
void config_timer();
/**
* @brief 配置网络参数
*/
void config_network();
/**
* @brief 配置管理主菜单
*/
void config_management_menu();
#endif // CONFIG_H #endif // CONFIG_H
-108
View File
@@ -1,108 +0,0 @@
/**
* @file game_mode.h
* @brief 五子棋游戏框架头文件
* @note 本文件定义了五子棋游戏的四种主要模式:
* 1. AI对战模式
* 2. 双人对战模式
* 3. 网络对战模式
* 4. 复盘模式
*/
#ifndef GAME_MODE_H
#define GAME_MODE_H
#include "gobang.h"
#include "config.h"
/**
* @brief 从用户获取整数输入
*
* @param prompt 提示信息
* @param min 最小值
* @param max 最大值
* @return int 输入的整数
*/
int get_integer_input(const char *prompt, int min, int max);
/**
* @brief 处理玩家回合
*
* @param x 玩家输入的横坐标
* @param y 玩家输入的纵坐标
* @return true 输入有效
* @return false 输入无效
*/
bool parse_player_input(int *x, int *y);
/**
* @brief 解析网络对战模式下的玩家输入
* @param x 行坐标指针
* @param y 列坐标指针
* @return true 有效坐标输入
* @return false 特殊命令或无效输入
*/
bool parse_network_player_input(int *x, int *y);
/**
* @brief 处理AI回合
*
* @param current_player 当前玩家
*/
bool handle_player_turn(int current_player);
/**
* @brief AI对战模式
* 实现玩家与AI的对战逻辑
*/
void run_ai_game();
/**
* @brief 双人对战模式
* 实现两个玩家之间的对战逻辑
*/
void run_pvp_game();
/**
* @brief 复盘模式
* 加载并重现历史对局
*/
void run_review_mode();
/**
* @brief 网络对战模式
* 实现两台设备之间的在线对战
*/
void run_network_game();
/**
* @brief 处理网络玩家回合
* @param current_player 当前玩家
* @param is_local_turn 是否为本地玩家回合
* @return true 回合处理成功
* @return false 游戏结束或网络错误
*/
bool handle_network_player_turn(int current_player, bool is_local_turn);
/**
* @brief 网络游戏主循环
* @return true 游戏正常结束
* @return false 网络错误
*/
bool network_game_loop();
/**
* @brief 显示游戏规则
*/
void show_game_rules();
/**
* @brief 显示关于游戏信息
*/
void show_about_game();
/**
* @brief 启动图形化界面
*/
void run_gui_mode();
#endif // GAME_MODE_H
+20 -24
View File
@@ -9,42 +9,38 @@
#include "type.h" #include "type.h"
#include "gobang.h" #include "gobang.h"
#include "network.h"
#include <stdbool.h> #include <stdbool.h>
#include <SDL3/SDL.h>
// ==================== 游戏核心变量 ==================== // ==================== 游戏核心变量 ====================
extern int BOARD_SIZE; // 当前实际使用的棋盘尺寸 extern int BOARD_SIZE; // 当前实际使用的棋盘尺寸
extern int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; // 棋盘状态存储数组 extern int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; // 棋盘状态存储数组
extern Step steps[MAX_STEPS]; // 存储所有落子步骤的数组 extern Step steps[MAX_STEPS]; // 存储所有落子步骤的数组
extern const int direction[4][2]; // 四个方向:向下、向右、右下、左下 extern const int direction[4][2]; // 四个方向:向下、向右、右下、左下
extern int step_count; // 当前步数计数器 extern int step_count; // 当前步数计数器
// ==================== 游戏配置变量 ==================== // ==================== 游戏配置变量 ====================
extern bool use_forbidden_moves; // 是否启用禁手规则的标志 extern bool use_forbidden_moves; // 是否启用禁手规则的标志
extern int use_timer; // 是否启用计时器的标志 extern int use_timer; // 是否启用计时器的标志
extern int time_limit; // 每回合的时间限制(秒,内部存储) extern int time_limit; // 每回合的时间限制(秒,内部存储)
extern int network_port; // 网络端口 extern int network_port; // 网络端口
extern int network_timeout; // 网络超时时间 extern int network_timeout; // 网络超时时间
// ==================== AI相关变量 ==================== // ==================== AI相关变量 ====================
extern double defense_coefficient; // 防守系数 extern double defense_coefficient; // 防守系数
extern int ai_difficulty; // AI难度 (1-5)
// ==================== 网络相关变量 ==================== // ==================== 网络相关变量 ====================
extern NetworkGameState network_state; // 网络游戏状态 extern NetworkGameState network_state; // 网络游戏状态
// ==================== GUI相关变量 ==================== // ==================== GUI相关变量 ====================
extern SDL_Window* window; // SDL窗口指针 extern int current_player_gui; // GUI当前玩家
extern SDL_Renderer* renderer; // SDL渲染器指针 extern int game_over; // 游戏结束标志
extern int gui_running; // GUI运行状态标志 extern char status_message[256]; // 状态消息
extern int current_player_gui; // GUI当前玩家
extern int game_over; // 游戏结束标志
extern char status_message[256]; // 状态消息
// ==================== 记录相关变量 ==================== // ==================== 记录相关变量 ====================
extern int player1_final_score; // 玩家1最终得分 extern int player1_final_score; // 玩家1最终得分
extern int player2_final_score; // 玩家2最终得分 extern int player2_final_score; // 玩家2最终得分
extern int scores_calculated; // 评分计算标志 extern int scores_calculated; // 评分计算标志
extern char winner_info[50]; // 存储胜负信息 extern char winner_info[50]; // 存储胜负信息
#endif // GLOBALS_H #endif // GLOBALS_H
+5
View File
@@ -20,6 +20,11 @@
// 函数原型 // 函数原型
// --- 游戏核心逻辑 --- // --- 游戏核心逻辑 ---
/**
* @brief 初始化棋盘,将所有位置设置为空(EMPTY)
*/
void empty_board();
/** /**
* @brief 检查指定坐标是否为有效落子点(在棋盘内且为空) * @brief 检查指定坐标是否为有效落子点(在棋盘内且为空)
* @param x 待检查的行坐标 (0-based) * @param x 待检查的行坐标 (0-based)
+23 -117
View File
@@ -1,15 +1,13 @@
/** /**
* @file gui.h * @file gui.h
* @brief 图形化用户界面头文件 * @brief 图形化用户界面头文件
* @note 使用SDL3库实现五子棋的图形化界面 * @note 使用IUP库实现五子棋的图形化界面
* @author 刘航宇 * @author 刘航宇
* @date 2025-01-15
*/ */
#ifndef GUI_H #ifndef GUI_H
#define GUI_H #define GUI_H
#include <SDL3/SDL.h>
#include "gobang.h" #include "gobang.h"
#include "config.h" #include "config.h"
#include "globals.h" #include "globals.h"
@@ -18,137 +16,45 @@
/** /**
* @brief 初始化GUI * @brief 初始化GUI
* @details 初始化SDL3图形库和游戏界面组件 * @details 初始化IUP图形库和游戏界面组件
* - 初始化SDL视频子系统
* - 创建游戏窗口(可调整大小)
* - 创建SDL渲染器
* - 初始化游戏状态和棋盘数据
* @return 成功返回0,失败返回-1 * @return 成功返回0,失败返回-1
* @note 窗口标题为"五子棋游戏 - SDL3版本"
* 窗口尺寸由WINDOW_WIDTH和WINDOW_HEIGHT定义
* 失败时会自动清理已创建的资源
*/ */
int init_gui(); int init_gui();
/** /**
* @brief 清理GUI资源 * @brief 清理GUI资源
* @details 按顺序释放所有SDL相关资源:
* - 销毁SDL渲染器
* - 销毁SDL窗口
* - 退出SDL子系统
* @note 函数会检查资源是否存在再进行释放
* 释放后将指针设置为NULL防止重复释放
* 程序退出时必须调用此函数避免内存泄漏
*/ */
void cleanup_gui(); void cleanup_gui();
/**
* @brief 渲染游戏画面
* @details 完整的游戏画面渲染流程:
* - 清空屏幕并设置背景色
* - 绘制棋盘网格和标记点
* - 绘制所有棋子
* - 绘制UI界面元素
* - 将渲染结果显示到屏幕
* @note 使用双缓冲技术,通过SDL_RenderPresent显示最终结果
* 背景色由GUI_COLOR_BACKGROUND定义
* 每帧都会完全重绘整个画面
*/
void render_game();
/**
* @brief 处理事件
* @details 处理所有SDL事件并执行相应操作:
* - SDL_EVENT_QUIT:用户关闭窗口
* - SDL_EVENT_KEY_DOWN:键盘按键(ESC退出)
* - SDL_EVENT_MOUSE_BUTTON_DOWN:鼠标点击落子
* @return 继续运行返回1,退出返回0
* @note 鼠标左键点击会转换为棋盘坐标并尝试落子
* 落子后会检查胜负并切换玩家
* 游戏结束后不再响应落子操作
*/
int handle_events();
/**
* @brief 绘制棋盘
* @details 绘制15x15的五子棋棋盘,包括:
* - 横竖交叉的网格线
* - 天元点(棋盘中心的标记点)
* - 四个星位(棋盘上的定位点)
* @note 使用SDL3渲染器绘制线条和填充矩形
* 棋盘线条颜色由GUI_COLOR_BOARD_LINE定义
* 天元点和星位用黑色小矩形标记
*/
void draw_board();
/**
* @brief 绘制棋子
* @details 遍历整个棋盘数组,绘制所有已落下的棋子:
* - 黑子:使用GUI_COLOR_BLACK_STONE颜色
* - 白子:使用GUI_COLOR_WHITE_STONE颜色
* - 每个棋子都有边框:使用GUI_COLOR_STONE_BORDER颜色
* @note 棋子绘制为圆形,半径由STONE_RADIUS定义
* 通过draw_circle函数实现圆形绘制
* 棋子位置根据棋盘坐标和CELL_SIZE计算屏幕坐标
*/
void draw_stones();
/**
* @brief 绘制UI元素
* @details 绘制游戏界面的用户交互元素:
* - 状态信息区域背景和边框
* - 当前玩家指示器(黑子或白子圆形)
* - 游戏状态显示区域
* @note 暂时使用简单图形代替文字显示
* 需要额外字体库支持文字渲染
* 指示器位置在棋盘右侧固定区域
*/
void draw_ui_elements();
/**
* @brief 绘制圆形
* @param center_x 圆心X坐标
* @param center_y 圆心Y坐标
* @param radius 半径
* @param color 颜色
* @details 使用像素级绘制实现圆形:
* - 遍历圆形外接矩形内的所有像素点
* - 计算每个像素到圆心的距离
* - 距离小于等于半径的像素点进行着色
* @note 采用暴力算法,性能较低但实现简单
* 适用于绘制棋子等小尺寸圆形
* SDL3没有内置圆形绘制函数,需要自实现
*/
void draw_circle(int center_x, int center_y, int radius, SDL_Color color);
/** /**
* @brief 屏幕坐标转棋盘坐标 * @brief 屏幕坐标转棋盘坐标
* @param screen_x 屏幕X坐标
* @param screen_y 屏幕Y坐标
* @param board_x 输出棋盘X坐标
* @param board_y 输出棋盘Y坐标
* @return 转换成功返回1,失败返回0
* @details 坐标转换算法:
* - 减去棋盘偏移量得到相对坐标
* - 加上半个格子尺寸实现就近取整
* - 除以格子尺寸得到棋盘坐标
* - 检查坐标是否在有效范围内
* @note 使用就近取整算法,点击格子中心附近都会定位到该格子
* 坐标范围检查确保不会越界访问棋盘数组
*/ */
int screen_to_board(int screen_x, int screen_y, int *board_x, int *board_y); int screen_to_board(int screen_x, int screen_y, int *board_x, int *board_y);
/** /**
* @brief 显示消息 * @brief 显示消息
* @param message 要显示的消息
* @details 消息显示功能:
* - 将消息复制到全局状态消息缓冲区
* - 同时在控制台输出消息内容
* - 确保字符串安全复制,防止缓冲区溢出
* @note 消息会存储在status_message全局变量中
* 字符串长度限制为缓冲区大小减1
* 消息可用于游戏状态提示和错误信息显示
*/ */
void show_message(const char *message); void show_message(const char *message);
/**
* @brief 启动玩家对战模式
*/
void start_pvp_game_gui();
/**
* @brief 启动人机对战模式
*/
void start_pve_game_gui();
/**
* @brief 启动复盘模式
*/
void start_replay_gui();
/**
* @brief 运行图形化界面模式
* @details 主循环处理事件、渲染画面和更新状态
*/
void run_gui_mode();
#endif // GUI_H #endif // GUI_H
+42
View File
@@ -0,0 +1,42 @@
#ifndef GUI_INTERNAL_H
#define GUI_INTERNAL_H
#include <iup.h>
// 全局变量声明 (在 gui_core.c 中定义)
extern Ihandle *dlg;
extern Ihandle *board_canvas;
extern Ihandle *lbl_player;
extern Ihandle *lbl_status;
extern int gui_game_mode; // 0: PvP, 1: PvE, 2: Replay
extern int replay_total_steps; // 复盘总步数
// 绘图函数 (在 gui_draw.c 中定义)
void set_draw_color(Ihandle *ih, unsigned char r, unsigned char g, unsigned char b);
void draw_board_iup(Ihandle *ih);
void draw_stones_iup(Ihandle *ih);
// 核心功能 (在 gui_core.c 中定义)
void update_ui_labels();
int screen_to_board(int screen_x, int screen_y, int *board_x, int *board_y);
// 游戏窗口 (在 gui_game.c 中定义)
void create_game_window();
void start_pvp_game_gui();
void start_pve_game_gui();
void start_network_game_gui(); // 新增:启动网络对战游戏窗口
int action_cb(Ihandle *ih);
int button_cb(Ihandle *ih, int button, int pressed, int x, int y, char *status);
int k_any_cb(Ihandle *ih, int c);
int btn_back_cb(Ihandle *ih);
int btn_undo_cb(Ihandle *ih);
int btn_save_cb(Ihandle *ih);
// 复盘功能 (在 gui_replay.c 中定义)
void select_replay_file_gui();
int btn_replay_prev_cb(Ihandle *ih);
int btn_replay_next_cb(Ihandle *ih);
int btn_replay_sel_ok_cb(Ihandle *ih);
int btn_replay_sel_cancel_cb(Ihandle *ih);
#endif // GUI_INTERNAL_H
+24
View File
@@ -0,0 +1,24 @@
#ifndef GUI_MENU_H
#define GUI_MENU_H
#include <iup.h>
// 主菜单对话框句柄,需要暴露给其他模块(如返回菜单时)
extern Ihandle *menu_dlg;
/**
* @brief 创建并显示主菜单
*/
void create_main_menu();
/**
* @brief 显示主菜单
*/
void show_main_menu();
/**
* @brief 隐藏主菜单
*/
void hide_main_menu();
#endif // GUI_MENU_H
-42
View File
@@ -1,42 +0,0 @@
/**
* @file init_board.h
* @brief 初始化游戏棋盘头文件
* @note 本文件定义了初始化游戏棋盘的相关函数和全局变量。
* 它负责设置游戏的初始状态,包括棋盘大小、玩家标识、游戏规则等。
*/
#ifndef INIT_BOARD_H
#define INIT_BOARD_H
#include "gobang.h"
// --- 游戏初始化 ---
/**
* @brief 初始化棋盘,将所有位置设置为空(EMPTY)
*/
void empty_board();
/**
* @brief 将当前棋盘状态打印到控制台
*/
void print_board();
/**
* @brief 设置当前游戏的棋盘大小
*/
void setup_board_size();
/**
* @brief 设置游戏选项,如是否启用禁手、计时器等
*/
void setup_game_options();
/**
* @brief 决定先手玩家
* @param player1 玩家1的标识
* @param player2 玩家2的标识
* @return 返回先手玩家的标识
*/
int determine_first_player(int player1, int player2);
#endif // INIT_H
+12 -21
View File
@@ -10,25 +10,16 @@
#ifndef NETWORK_H #ifndef NETWORK_H
#define NETWORK_H #define NETWORK_H
#include "gobang.h"
#include "type.h" #include "type.h"
#include "config.h" #include "config.h"
#include <stdbool.h> #include <stdbool.h>
#include <enet/enet.h> // 引入 ENet 头文件
#ifdef _WIN32 // 网络状态结构体在 type.h 中定义,我们需要修改 type.h 来包含 ENet 类型
#include <winsock2.h> // 或者在这里重新定义(如果 type.h 中可以移除旧的定义)
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib") // 全局网络状态
#else extern NetworkGameState network_state;
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SOCKET int
#define INVALID_SOCKET -1
#define SOCKET_ERROR -1
#define closesocket close
#endif
// 函数声明 // 函数声明
@@ -59,7 +50,7 @@ bool create_server(int port);
* @return true 连接成功 * @return true 连接成功
* @return false 连接失败 * @return false 连接失败
*/ */
bool connect_to_server(const char* ip, int port); bool connect_to_server(const char *ip, int port);
/** /**
* @brief 发送网络消息 * @brief 发送网络消息
@@ -67,16 +58,16 @@ bool connect_to_server(const char* ip, int port);
* @return true 发送成功 * @return true 发送成功
* @return false 发送失败 * @return false 发送失败
*/ */
bool send_network_message(const NetworkMessage* msg); bool send_network_message(const NetworkMessage *msg);
/** /**
* @brief 接收网络消息 * @brief 接收网络消息
* @param msg 接收消息的缓冲区 * @param msg 接收消息的缓冲区
* @param timeout_ms 超时时间(毫秒),0表示阻塞等待 * @param timeout_ms 超时时间(毫秒),0表示阻塞等待
* @return true 接收成功 * @return true 接收成功
* @return false 接收失败或超时 * @return false 接收失败或超时
*/ */
bool receive_network_message(NetworkMessage* msg, int timeout_ms); bool receive_network_message(NetworkMessage *msg, int timeout_ms);
/** /**
* @brief 断开网络连接 * @brief 断开网络连接
@@ -97,7 +88,7 @@ bool is_network_connected();
* @return true 获取成功 * @return true 获取成功
* @return false 获取失败 * @return false 获取失败
*/ */
bool get_local_ip(char* ip_buffer, int buffer_size); bool get_local_ip(char *ip_buffer, int buffer_size);
/** /**
* @brief 发送落子消息 * @brief 发送落子消息
@@ -115,7 +106,7 @@ bool send_move(int x, int y, int player_id);
* @return true 发送成功 * @return true 发送成功
* @return false 发送失败 * @return false 发送失败
*/ */
bool send_chat_message(const char* message); bool send_chat_message(const char *message);
/** /**
* @brief 发送认输消息 * @brief 发送认输消息
-12
View File
@@ -10,12 +10,6 @@
#include "gobang.h" #include "gobang.h"
// --- 复盘与记录功能 --- // --- 复盘与记录功能 ---
/**
* @brief 进入复盘流程,回顾整局游戏
* @param game_mode 游戏模式(1为人机对战,2为双人对战)
*/
void review_process(int game_mode);
/** /**
* @brief 将当前对局记录保存到文件 * @brief 将当前对局记录保存到文件
* @param filename 要保存到的文件名 * @param filename 要保存到的文件名
@@ -24,12 +18,6 @@ void review_process(int game_mode);
*/ */
int save_game_to_file(const char *filename, int game_mode); int save_game_to_file(const char *filename, int game_mode);
/**
* @brief 处理保存游戏记录的逻辑
* @param game_mode 游戏模式
*/
void handle_save_record(int game_mode);
/** /**
* @brief 从文件加载游戏记录 * @brief 从文件加载游戏记录
* @param filename 要加载的文件名 * @param filename 要加载的文件名
+42 -38
View File
@@ -10,32 +10,29 @@
#include <stdbool.h> #include <stdbool.h>
#include <time.h> #include <time.h>
#include <stdint.h>
#ifdef _WIN32
#include <winsock2.h>
#else
#define SOCKET int
#endif
// ==================== 游戏核心数据结构 ==================== // ==================== 游戏核心数据结构 ====================
/** /**
* @brief 记录一步棋的详细信息 * @brief 记录一步棋的详细信息
*/ */
typedef struct { typedef struct
int player; // 执行该步的玩家标识 {
int x; // 落子的行坐标 (0-based) int player; // 执行该步的玩家标识
int y; // 落子的坐标 (0-based) int x; // 落子的坐标 (0-based)
int y; // 落子的列坐标 (0-based)
} Step; } Step;
/** /**
* @brief 存储在特定方向上棋子连续性的信息 * @brief 存储在特定方向上棋子连续性的信息
* @details 用于评估棋形,例如判断活三、冲四等关键形态 * @details 用于评估棋形,例如判断活三、冲四等关键形态
*/ */
typedef struct { typedef struct
int continuous_chess; // 连续同色棋子的数量 {
bool check_start; // 棋子序列的起始端是否为空位(即是否开放) int continuous_chess; // 连续同色棋子的数量
bool check_end; // 棋子序列的末尾端是否为空位(即是否开放) bool check_start; // 棋子序列的起始端是否为空位(即是否开放)
bool check_end; // 棋子序列的末尾端是否为空位(即是否开放)
} DirInfo; } DirInfo;
// ==================== AI相关数据结构 ==================== // ==================== AI相关数据结构 ====================
@@ -44,22 +41,24 @@ typedef struct {
* @brief 移动排序结构体 * @brief 移动排序结构体
* @details 用于AI移动排序,存储候选移动及其评估分数 * @details 用于AI移动排序,存储候选移动及其评估分数
*/ */
typedef struct { typedef struct
int x, y; // 位置坐标 {
int score; // 评估分数 int x, y; // 位置坐标
int score; // 评估分数
} ScoredMove; } ScoredMove;
/** /**
* @brief 威胁类型枚举 * @brief 威胁类型枚举
* @details 用于AI威胁检测系统 * @details 用于AI威胁检测系统
*/ */
typedef enum { typedef enum
THREAT_NONE = 0, // 无威胁 {
THREAT_WIN = 5, // 直接获胜 THREAT_NONE = 0, // 无威胁
THREAT_FOUR = 4, // 活四/冲四 THREAT_WIN = 5, // 直接获胜
THREAT_THREE = 3, // 活 THREAT_FOUR = 4, // 活四/冲四
THREAT_DOUBLE = 2, // 双威胁 THREAT_THREE = 3, // 活三
THREAT_POTENTIAL = 1 // 潜在威胁 THREAT_DOUBLE = 2, // 威胁
THREAT_POTENTIAL = 1 // 潜在威胁
} ThreatLevel; } ThreatLevel;
// ==================== 网络相关数据结构 ==================== // ==================== 网络相关数据结构 ====================
@@ -68,26 +67,31 @@ typedef enum {
* @brief 网络消息结构 * @brief 网络消息结构
* @details 用于网络对战中的消息传输 * @details 用于网络对战中的消息传输
*/ */
typedef struct { typedef struct
int type; // 消息类型 {
int player_id; // 玩家ID int type; // 消息类型
int x, y; // 坐标(用于落子) int player_id; // 玩家ID
char message[256]; // 消息内容(用于聊天等 int x, y; // 坐标(用于落子
time_t timestamp; // 时间戳 char message[256]; // 消息内容(用于聊天等)
time_t timestamp; // 时间戳
} NetworkMessage; } NetworkMessage;
/** /**
* @brief 网络游戏状态结构 * @brief 网络游戏状态结构
* @details 用于管理网络游戏状态 * @details 用于管理网络游戏状态
*/ */
typedef struct { // ENet 头文件需要前置声明或直接包含,但在 type.h 中包含可能引起循环依赖
SOCKET socket; // 套接字 // 我们可以使用 void* 来避免在 type.h 中包含 enet.h
bool is_server; // 是否为服务器 typedef struct
bool is_connected; // 是否已连接 {
int local_player_id; // 本地玩家ID void *host; // ENetHost * (Server 或 Client)
int remote_player_id; // 远程玩家ID void *peer; // ENetPeer * (连接的对象)
char remote_ip[16]; // 远程IP地址(MAX_IP_LENGTH = 16 bool is_server; // 是否为服务器(主机)
int port; // 端口号 bool is_connected; // 是否已连接
int local_player_id; // 本地玩家ID
int remote_player_id; // 远程玩家ID
char remote_ip[64]; // 远程IP
int port; // 端口
} NetworkGameState; } NetworkGameState;
#endif // TYPE_H #endif // TYPE_H
-69
View File
@@ -1,69 +0,0 @@
/**
* @file ui.h
* @brief
* @note 本文件定义了用户界面相关的函数和数据结构。
* 它负责处理用户输入、显示游戏界面、提示信息等与用户交互的功能。
*/
#ifndef UI_H
#define UI_H
#include "gobang.h"
/**
* @brief UI模块 - 用户界面相关功能
* @author 刘航宇
* @date 2025-07-10
* @version 5.0
*/
/**
* @brief 显示游戏主菜单
*/
void display_main_menu();
/**
* @brief 显示棋盘
*/
void display_board();
/**
* @brief 显示游戏状态信息
* @param current_player 当前玩家
* @param step_count 当前步数
*/
void display_game_status(int current_player, int step_count);
/**
* @brief 显示获胜信息
* @param winner 获胜者
*/
void display_winner(int winner);
/**
* @brief 显示游戏设置菜单
*/
void display_settings_menu();
/**
* @brief 清屏函数
*/
void clear_screen();
/**
* @brief 暂停等待用户输入
* @param prompt 提示信息
*/
void pause_for_input(const char* prompt);
/**
* @brief 显示游戏规则
*/
void display_game_rules();
/**
* @brief 显示关于信息
*/
void display_about();
#endif // UI_H
+10 -23
View File
@@ -8,7 +8,6 @@ AppUpdatesURL=https://github.com/LHY0125/gobang.git
DefaultDirName={autopf}\Gobang DefaultDirName={autopf}\Gobang
DefaultGroupName=五子棋游戏 DefaultGroupName=五子棋游戏
AllowNoIcons=yes AllowNoIcons=yes
LicenseFile=..\README.md
OutputDir=dist OutputDir=dist
OutputBaseFilename=Gobang_Inno_Setup OutputBaseFilename=Gobang_Inno_Setup
SetupIconFile= SetupIconFile=
@@ -24,33 +23,21 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files] [Files]
Source: "..\gobang_console.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "..\bin\gobang_gui.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gobang_gui.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "..\bin\iup.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\SDL3.dll"; DestDir: "{app}"; Flags: ignoreversion ; 允许文件夹为空时不报错
Source: "..\include\*"; DestDir: "{app}\include"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\bin\records\*"; DestDir: "{app}\records"; Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist
Source: "..\src\*"; DestDir: "{app}\src"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\MD\*"; DestDir: "{app}\MD"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\TXT\*"; DestDir: "{app}\TXT"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\records\*"; DestDir: "{app}\records"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\installer\*"; DestDir: "{app}\installer"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\compile.bat"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\gobang_config.ini"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\Makefile"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\README.md"; DestDir: "{app}"; Flags: ignoreversion
[Icons] [Icons]
Name: "{group}\五子棋游戏(控制台版)"; Filename: "{app}\gobang_console.exe" Name: "{group}\五子棋游戏(图形界面版)"; Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"
Name: "{group}\五子棋游戏(图形界面版)"; Filename: "{app}\gobang_gui.exe"
Name: "{group}\{cm:UninstallProgram,五子棋游戏}"; Filename: "{uninstallexe}" Name: "{group}\{cm:UninstallProgram,五子棋游戏}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\五子棋游戏"; Filename: "{app}\gobang_gui.exe"; Tasks: desktopicon Name: "{autodesktop}\五子棋游戏"; Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"; Tasks: desktopicon
[Run] [Run]
Filename: "{app}\gobang_gui.exe"; Description: "{cm:LaunchProgram,五子棋游戏}"; Flags: nowait postinstall skipifsilent Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"; Description: "{cm:LaunchProgram,五子棋游戏}"; Flags: nowait postinstall skipifsilent
[UninstallDelete] [UninstallDelete]
Type: filesandordirs; Name: "{app}\records" Type: filesandordirs; Name: "{app}\records"
Type: filesandordirs; Name: "{app}\include" Type: files; Name: "{app}\gobang_gui.exe"
Type: filesandordirs; Name: "{app}\src" Type: files; Name: "{app}\iup.dll"
Type: filesandordirs; Name: "{app}\MD" Type: dirifempty; Name: "{app}"
Type: filesandordirs; Name: "{app}\TXT"
Type: filesandordirs; Name: "{app}\installer"
-162
View File
@@ -1,162 +0,0 @@
; NSIS Install Script - Gobang Game
; Version: v8.3
; Author: LHY
!define PRODUCT_NAME "Gobang Game"
!define PRODUCT_VERSION "8.3"
!define PRODUCT_PUBLISHER "LHY"
!define PRODUCT_WEB_SITE "https://github.com/LHY0125/gobang.git"
!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\gobang_gui.exe"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
; Include Modern UI
!include "MUI2.nsh"
; MUI Settings
!define MUI_ABORTWARNING
!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
; Welcome page
!insertmacro MUI_PAGE_WELCOME
; License page
!insertmacro MUI_PAGE_LICENSE "..\README.md"
; Components page
!insertmacro MUI_PAGE_COMPONENTS
; Directory page
!insertmacro MUI_PAGE_DIRECTORY
; Install page
!insertmacro MUI_PAGE_INSTFILES
; Finish page
!define MUI_FINISHPAGE_RUN "$INSTDIR\gobang_gui.exe"
!insertmacro MUI_PAGE_FINISH
; Uninstall page
!insertmacro MUI_UNPAGE_INSTFILES
; Language files
!insertmacro MUI_LANGUAGE "SimpChinese"
; Installer attributes
Name "${PRODUCT_NAME} ${PRODUCT_VERSION}"
OutFile "dist\Gobang_NSIS_Setup.exe"
InstallDir "$PROGRAMFILES\Gobang"
InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" ""
ShowInstDetails show
ShowUnInstDetails show
; Version information
VIProductVersion "1.0.0.0"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "ProductName" "${PRODUCT_NAME}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "Comments" "Gobang Game - Classic five-in-a-row strategy game with AI and network support"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "CompanyName" "${PRODUCT_PUBLISHER}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalTrademarks" "MIT License"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "LegalCopyright" "© 2025 ${PRODUCT_PUBLISHER}"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileDescription" "${PRODUCT_NAME} Setup"
VIAddVersionKey /LANG=${LANG_SIMPCHINESE} "FileVersion" "${PRODUCT_VERSION}"
Section "Main Program" SEC01
SectionIn RO
SetOutPath "$INSTDIR"
SetOverwrite ifnewer
File "..\gobang_console.exe"
File "..\gobang_gui.exe"
File "..\SDL3.dll"
File "..\compile.bat"
File "..\gobang_config.ini"
File "..\Makefile"
File "..\README.md"
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Gobang Console.lnk" "$INSTDIR\gobang_console.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Gobang GUI.lnk" "$INSTDIR\gobang_gui.exe"
CreateShortCut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\gobang_gui.exe"
SectionEnd
Section "Source Code" SEC02
SetOutPath "$INSTDIR\include"
File /r "..\include\*.*"
SetOutPath "$INSTDIR\src"
File /r "..\src\*.*"
SetOutPath "$INSTDIR\installer"
File /r "..\installer\*.*"
SectionEnd
Section "Game Records" SEC03
SetOutPath "$INSTDIR\records"
File /r "..\records\*.*"
SectionEnd
Section "Documentation" SEC04
SetOutPath "$INSTDIR\MD"
File /r "..\MD\*.*"
SetOutPath "$INSTDIR\TXT"
File /r "..\TXT\*.*"
SectionEnd
Section -AdditionalIcons
WriteIniStr "$INSTDIR\${PRODUCT_NAME}.url" "InternetShortcut" "URL" "${PRODUCT_WEB_SITE}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk" "$INSTDIR\${PRODUCT_NAME}.url"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\uninst.exe"
SectionEnd
Section -Post
WriteUninstaller "$INSTDIR\uninst.exe"
WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\gobang_gui.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\gobang_gui.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
; Component descriptions
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
!insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "Install main program files. This is a required component."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Install source code files, including headers and implementation files."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "Install game records and save files."
!insertmacro MUI_DESCRIPTION_TEXT ${SEC04} "Install project documentation, including user manual and technical documents."
!insertmacro MUI_FUNCTION_DESCRIPTION_END
Function un.onUninstSuccess
HideWindow
MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) has been successfully removed from your computer."
FunctionEnd
Function un.onInit
MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2
Abort
FunctionEnd
Section Uninstall
Delete "$INSTDIR\${PRODUCT_NAME}.url"
Delete "$INSTDIR\uninst.exe"
Delete "$INSTDIR\gobang_console.exe"
Delete "$INSTDIR\gobang_gui.exe"
Delete "$INSTDIR\SDL3.dll"
Delete "$INSTDIR\compile.bat"
Delete "$INSTDIR\gobang_config.ini"
Delete "$INSTDIR\Makefile"
Delete "$INSTDIR\README.md"
RMDir /r "$INSTDIR\include"
RMDir /r "$INSTDIR\src"
RMDir /r "$INSTDIR\installer"
RMDir /r "$INSTDIR\records"
RMDir /r "$INSTDIR\MD"
RMDir /r "$INSTDIR\TXT"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Website.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Gobang Console.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Gobang GUI.lnk"
Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
RMDir "$SMPROGRAMS\${PRODUCT_NAME}"
RMDir "$INSTDIR"
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}"
SetAutoClose true
SectionEnd
+21
View File
@@ -0,0 +1,21 @@
on: [push, pull_request]
name: CMake
jobs:
cmake-build:
name: CMake ${{ matrix.os }} ${{ matrix.build_type }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
build_type: ["Debug", "Release"]
steps:
- uses: actions/checkout@v3
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{ matrix.build_type }}
+70
View File
@@ -0,0 +1,70 @@
# Potential build directories
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
[Bb]in/
[Dd]ebug/
[Dd]ebugPublic/
[Ll]og/
[Ll]ogs/
[Oo]bj/
[Rr]elease/
[Rr]eleases/
[Ww][Ii][Nn]32/
bld/
build/
builds/
out/
x64/
x86/
# VS
.vs/
.vscode/
!.vscode/extensions.json
!.vscode/launch.json
!.vscode/settings.json
!.vscode/tasks.json
# CMake
_deps
CMakeCache.txt
CMakeFiles
CMakeLists.txt.user
CMakeScripts
CMakeUserPresets.json
CTestTestfile.cmake
cmake_install.cmake
compile_commands.json
install_manifest.txt
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects
*.dll
*.so
*.so.*
*.dylib
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
+119
View File
@@ -0,0 +1,119 @@
cmake_minimum_required(VERSION 2.8.12...3.20)
project(enet)
# The "configure" step.
include(CheckFunctionExists)
include(CheckStructHasMember)
include(CheckTypeSize)
check_function_exists("fcntl" HAS_FCNTL)
check_function_exists("poll" HAS_POLL)
check_function_exists("getaddrinfo" HAS_GETADDRINFO)
check_function_exists("getnameinfo" HAS_GETNAMEINFO)
check_function_exists("gethostbyname_r" HAS_GETHOSTBYNAME_R)
check_function_exists("gethostbyaddr_r" HAS_GETHOSTBYADDR_R)
check_function_exists("inet_pton" HAS_INET_PTON)
check_function_exists("inet_ntop" HAS_INET_NTOP)
check_c_source_compiles("
#include <stddef.h>
struct S { int a; double b; };
int main() {
return (int)offsetof(struct S, b);
}
" HAS_OFFSETOF)
check_struct_has_member("struct msghdr" "msg_flags" "sys/types.h;sys/socket.h" HAS_MSGHDR_FLAGS)
set(CMAKE_EXTRA_INCLUDE_FILES "sys/types.h" "sys/socket.h")
check_type_size("socklen_t" HAS_SOCKLEN_T BUILTIN_TYPES_ONLY)
unset(CMAKE_EXTRA_INCLUDE_FILES)
if(MSVC)
add_definitions(-W3)
else()
add_definitions(-Wno-error)
endif()
if(HAS_FCNTL)
add_definitions(-DHAS_FCNTL=1)
endif()
if(HAS_POLL)
add_definitions(-DHAS_POLL=1)
endif()
if(HAS_GETNAMEINFO)
add_definitions(-DHAS_GETNAMEINFO=1)
endif()
if(HAS_GETADDRINFO)
add_definitions(-DHAS_GETADDRINFO=1)
endif()
if(HAS_GETHOSTBYNAME_R)
add_definitions(-DHAS_GETHOSTBYNAME_R=1)
endif()
if(HAS_GETHOSTBYADDR_R)
add_definitions(-DHAS_GETHOSTBYADDR_R=1)
endif()
if(HAS_INET_PTON)
add_definitions(-DHAS_INET_PTON=1)
endif()
if(HAS_INET_NTOP)
add_definitions(-DHAS_INET_NTOP=1)
endif()
if(HAS_OFFSETOF)
add_definitions(-DHAS_OFFSETOF=1)
endif()
if(HAS_MSGHDR_FLAGS)
add_definitions(-DHAS_MSGHDR_FLAGS=1)
endif()
if(HAS_SOCKLEN_T)
add_definitions(-DHAS_SOCKLEN_T=1)
endif()
include_directories(${PROJECT_SOURCE_DIR}/include)
set(INCLUDE_FILES_PREFIX include/enet)
set(INCLUDE_FILES
${INCLUDE_FILES_PREFIX}/callbacks.h
${INCLUDE_FILES_PREFIX}/enet.h
${INCLUDE_FILES_PREFIX}/list.h
${INCLUDE_FILES_PREFIX}/protocol.h
${INCLUDE_FILES_PREFIX}/time.h
${INCLUDE_FILES_PREFIX}/types.h
${INCLUDE_FILES_PREFIX}/unix.h
${INCLUDE_FILES_PREFIX}/utility.h
${INCLUDE_FILES_PREFIX}/win32.h
)
set(SOURCE_FILES
callbacks.c
compress.c
host.c
list.c
packet.c
peer.c
protocol.c
unix.c
win32.c)
source_group(include FILES ${INCLUDE_FILES})
source_group(source FILES ${SOURCE_FILES})
if(WIN32 AND BUILD_SHARED_LIBS AND (MSVC OR CMAKE_CXX_COMPILER_ID MATCHES "Clang"))
add_definitions(-DENET_DLL=1)
add_definitions(-DENET_BUILDING_LIB)
endif()
add_library(enet
${INCLUDE_FILES}
${SOURCE_FILES}
)
if (WIN32)
target_link_libraries(enet winmm ws2_32)
endif()
include(GNUInstallDirs)
install(TARGETS enet
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/enet
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
+209
View File
@@ -0,0 +1,209 @@
ENet 1.3.18 (April 14, 2024):
* Packet sending performance improvements
* MTU negotiation fixes
* Checksum alignment fix
* No more dynamic initialization of checksum table
* ENET_SOCKOPT_TTL
* Other miscellaneous small improvements
ENet 1.3.17 (November 15, 2020):
* fixes for sender getting too far ahead of receiver that can cause instability with reliable packets
ENet 1.3.16 (September 8, 2020):
* fix bug in unreliable fragment queuing
* use single output queue for reliable and unreliable packets for saner ordering
* revert experimental throttle changes that were less stable than prior algorithm
ENet 1.3.15 (April 20, 2020):
* quicker RTT initialization
* use fractional precision for RTT calculations
* fixes for packet throttle with low RTT variance
* miscellaneous socket bug fixes
ENet 1.3.14 (January 27, 2019):
* bug fix for enet_peer_disconnect_later()
* use getaddrinfo and getnameinfo where available
* miscellaneous cleanups
ENet 1.3.13 (April 30, 2015):
* miscellaneous bug fixes
* added premake and cmake support
* miscellaneous documentation cleanups
ENet 1.3.12 (April 24, 2014):
* added maximumPacketSize and maximumWaitingData fields to ENetHost to limit the amount of
data waiting to be delivered on a peer (beware that the default maximumPacketSize is
32MB and should be set higher if desired as should maximumWaitingData)
ENet 1.3.11 (December 26, 2013):
* allow an ENetHost to connect to itself
* fixed possible bug with disconnect notifications during connect attempts
* fixed some preprocessor definition bugs
ENet 1.3.10 (October 23, 2013);
* doubled maximum reliable window size
* fixed RCVTIMEO/SNDTIMEO socket options and also added NODELAY
ENet 1.3.9 (August 19, 2013):
* added duplicatePeers option to ENetHost which can limit the number of peers from duplicate IPs
* added enet_socket_get_option() and ENET_SOCKOPT_ERROR
* added enet_host_random_seed() platform stub
ENet 1.3.8 (June 2, 2013):
* added enet_linked_version() for checking the linked version
* added enet_socket_get_address() for querying the local address of a socket
* silenced some debugging prints unless ENET_DEBUG is defined during compilation
* handle EINTR in enet_socket_wait() so that enet_host_service() doesn't propagate errors from signals
* optimized enet_host_bandwidth_throttle() to be less expensive for large numbers of peers
ENet 1.3.7 (March 6, 2013):
* added ENET_PACKET_FLAG_SENT to indicate that a packet is being freed because it has been sent
* added userData field to ENetPacket
* changed how random seed is generated on Windows to avoid import warnings
* fixed case where disconnects could be generated with no preceding connect event
ENet 1.3.6 (December 11, 2012):
* added support for intercept callback in ENetHost that can be used to process raw packets before ENet
* added enet_socket_shutdown() for issuing shutdown on a socket
* fixed enet_socket_connect() to not error on non-blocking connects
* fixed bug in MTU negotiation during connections
ENet 1.3.5 (July 31, 2012):
* fixed bug in unreliable packet fragment queuing
ENet 1.3.4 (May 29, 2012):
* added enet_peer_ping_interval() for configuring per-peer ping intervals
* added enet_peer_timeout() for configuring per-peer timeouts
* added protocol packet size limits
ENet 1.3.3 (June 28, 2011):
* fixed bug with simultaneous disconnects not dispatching events
ENet 1.3.2 (May 31, 2011):
* added support for unreliable packet fragmenting via the packet flag
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT
* fixed regression in unreliable packet queuing
* added check against received port to limit some forms of IP-spoofing
ENet 1.3.1 (February 10, 2011):
* fixed bug in tracking of reliable data in transit
* reliable data window size now scales with the throttle
* fixed bug in fragment length calculation when checksums are used
ENet 1.3.0 (June 5, 2010):
* enet_host_create() now requires the channel limit to be specified as
a parameter
* enet_host_connect() now accepts a data parameter which is supplied
to the receiving receiving host in the event data field for a connect event
* added an adaptive order-2 PPM range coder as a built-in compressor option
which can be set with enet_host_compress_with_range_coder()
* added support for packet compression configurable with a callback
* improved session number handling to not rely on the packet checksum
field, saving 4 bytes per packet unless the checksum option is used
* removed the dependence on the rand callback for session number handling
Caveats: This version is not protocol compatible with the 1.2 series or
earlier. The enet_host_connect and enet_host_create API functions require
supplying additional parameters.
ENet 1.2.5 (June 28, 2011):
* fixed bug with simultaneous disconnects not dispatching events
ENet 1.2.4 (May 31, 2011):
* fixed regression in unreliable packet queuing
* added check against received port to limit some forms of IP-spoofing
ENet 1.2.3 (February 10, 2011):
* fixed bug in tracking reliable data in transit
ENet 1.2.2 (June 5, 2010):
* checksum functionality is now enabled by setting a checksum callback
inside ENetHost instead of being a configure script option
* added totalSentData, totalSentPackets, totalReceivedData, and
totalReceivedPackets counters inside ENetHost for getting usage
statistics
* added enet_host_channel_limit() for limiting the maximum number of
channels allowed by connected peers
* now uses dispatch queues for event dispatch rather than potentially
unscalable array walking
* added no_memory callback that is called when a malloc attempt fails,
such that if no_memory returns rather than aborts (the default behavior),
then the error is propagated to the return value of the API calls
* now uses packed attribute for protocol structures on platforms with
strange alignment rules
* improved autoconf build system contributed by Nathan Brink allowing
for easier building as a shared library
Caveats: If you were using the compile-time option that enabled checksums,
make sure to set the checksum callback inside ENetHost to enet_crc32 to
regain the old behavior. The ENetCallbacks structure has added new fields,
so make sure to clear the structure to zero before use if
using enet_initialize_with_callbacks().
ENet 1.2.1 (November 12, 2009):
* fixed bug that could cause disconnect events to be dropped
* added thin wrapper around select() for portable usage
* added ENET_SOCKOPT_REUSEADDR socket option
* factored enet_socket_bind()/enet_socket_listen() out of enet_socket_create()
* added contributed Code::Blocks build file
ENet 1.2 (February 12, 2008):
* fixed bug in VERIFY_CONNECT acknowledgement that could cause connect
attempts to occasionally timeout
* fixed acknowledgements to check both the outgoing and sent queues
when removing acknowledged packets
* fixed accidental bit rot in the MSVC project file
* revised sequence number overflow handling to address some possible
disconnect bugs
* added enet_host_check_events() for getting only local queued events
* factored out socket option setting into enet_socket_set_option() so
that socket options are now set separately from enet_socket_create()
Caveats: While this release is superficially protocol compatible with 1.1,
differences in the sequence number overflow handling can potentially cause
random disconnects.
ENet 1.1 (June 6, 2007):
* optional CRC32 just in case someone needs a stronger checksum than UDP
provides (--enable-crc32 configure option)
* the size of packet headers are half the size they used to be (so less
overhead when sending small packets)
* enet_peer_disconnect_later() that waits till all queued outgoing
packets get sent before issuing an actual disconnect
* freeCallback field in individual packets for notification of when a
packet is about to be freed
* ENET_PACKET_FLAG_NO_ALLOCATE for supplying pre-allocated data to a
packet (can be used in concert with freeCallback to support some custom
allocation schemes that the normal memory allocation callbacks would
normally not allow)
* enet_address_get_host_ip() for printing address numbers
* promoted the enet_socket_*() functions to be part of the API now
* a few stability/crash fixes
+2303
View File
File diff suppressed because it is too large Load Diff
+191
View File
@@ -0,0 +1,191 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.6 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title="Home"/>
<tab type="user" visible="yes" title="Features" url="@ref Features" />
<tab type="user" visible="yes" title="Downloads" url="@ref Downloads" />
<tab type="user" visible="yes" title="Installation" url="@ref Installation" />
<tab type="user" visible="yes" title="Tutorial" url="@ref Tutorial" />
<tab type="user" visible="yes" title="Mailing List" url="@ref MailingList" />
<tab type="user" visible="yes" title="IRC Channel" url="@ref IRCChannel" />
<tab type="user" visible="yes" title="FAQ" url="@ref FAQ" />
<tab type="user" visible="yes" title="License" url="@ref License" />
<tab type="usergroup" visible="yes" title="Documentation" briefdescription="Documentation">
<tab type="modules" visible="yes" title="Functions" intro=""/>
<tab type="classlist" visible="yes" title="Data Structures" intro=""/>
<tab type="filelist" visible="yes" title="Files" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<classes visible="yes" title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<classes visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>
+7
View File
@@ -0,0 +1,7 @@
Copyright (c) 2002-2024 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+22
View File
@@ -0,0 +1,22 @@
pkgconfigdir = $(libdir)/pkgconfig
nodist_pkgconfig_DATA = libenet.pc
enetincludedir=$(includedir)/enet
enetinclude_HEADERS = \
include/enet/callbacks.h \
include/enet/enet.h \
include/enet/list.h \
include/enet/protocol.h \
include/enet/time.h \
include/enet/types.h \
include/enet/unix.h \
include/enet/utility.h \
include/enet/win32.h
lib_LTLIBRARIES = libenet.la
libenet_la_SOURCES = callbacks.c compress.c host.c list.c packet.c peer.c protocol.c unix.c win32.c
# see info '(libtool) Updating version info' before making a release
libenet_la_LDFLAGS = $(AM_LDFLAGS) -version-info 7:6:0
AM_CPPFLAGS = -I$(top_srcdir)/include
ACLOCAL_AMFLAGS = -Im4
+15
View File
@@ -0,0 +1,15 @@
Please visit the ENet homepage at http://sauerbraten.org/enet/ for installation
and usage instructions.
If you obtained this package from github, the quick description on how to build
is:
# Generate the build system.
autoreconf -vfi
# Compile and install the library.
./configure && make && make install
+53
View File
@@ -0,0 +1,53 @@
/**
@file callbacks.c
@brief ENet callback functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
static ENetCallbacks callbacks = { malloc, free, abort };
int
enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits)
{
if (version < ENET_VERSION_CREATE (1, 3, 0))
return -1;
if (inits -> malloc != NULL || inits -> free != NULL)
{
if (inits -> malloc == NULL || inits -> free == NULL)
return -1;
callbacks.malloc = inits -> malloc;
callbacks.free = inits -> free;
}
if (inits -> no_memory != NULL)
callbacks.no_memory = inits -> no_memory;
return enet_initialize ();
}
ENetVersion
enet_linked_version (void)
{
return ENET_VERSION;
}
void *
enet_malloc (size_t size)
{
void * memory = callbacks.malloc (size);
if (memory == NULL)
callbacks.no_memory ();
return memory;
}
void
enet_free (void * memory)
{
callbacks.free (memory);
}
+654
View File
@@ -0,0 +1,654 @@
/**
@file compress.c
@brief An adaptive order-2 PPM range coder
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
typedef struct _ENetSymbol
{
/* binary indexed tree of symbols */
enet_uint8 value;
enet_uint8 count;
enet_uint16 under;
enet_uint16 left, right;
/* context defined by this symbol */
enet_uint16 symbols;
enet_uint16 escapes;
enet_uint16 total;
enet_uint16 parent;
} ENetSymbol;
/* adaptation constants tuned aggressively for small packet sizes rather than large file compression */
enum
{
ENET_RANGE_CODER_TOP = 1<<24,
ENET_RANGE_CODER_BOTTOM = 1<<16,
ENET_CONTEXT_SYMBOL_DELTA = 3,
ENET_CONTEXT_SYMBOL_MINIMUM = 1,
ENET_CONTEXT_ESCAPE_MINIMUM = 1,
ENET_SUBCONTEXT_ORDER = 2,
ENET_SUBCONTEXT_SYMBOL_DELTA = 2,
ENET_SUBCONTEXT_ESCAPE_DELTA = 5
};
/* context exclusion roughly halves compression speed, so disable for now */
#undef ENET_CONTEXT_EXCLUSION
typedef struct _ENetRangeCoder
{
/* only allocate enough symbols for reasonable MTUs, would need to be larger for large file compression */
ENetSymbol symbols[4096];
} ENetRangeCoder;
void *
enet_range_coder_create (void)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) enet_malloc (sizeof (ENetRangeCoder));
if (rangeCoder == NULL)
return NULL;
return rangeCoder;
}
void
enet_range_coder_destroy (void * context)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
if (rangeCoder == NULL)
return;
enet_free (rangeCoder);
}
#define ENET_SYMBOL_CREATE(symbol, value_, count_) \
{ \
symbol = & rangeCoder -> symbols [nextSymbol ++]; \
symbol -> value = value_; \
symbol -> count = count_; \
symbol -> under = count_; \
symbol -> left = 0; \
symbol -> right = 0; \
symbol -> symbols = 0; \
symbol -> escapes = 0; \
symbol -> total = 0; \
symbol -> parent = 0; \
}
#define ENET_CONTEXT_CREATE(context, escapes_, minimum) \
{ \
ENET_SYMBOL_CREATE (context, 0, 0); \
(context) -> escapes = escapes_; \
(context) -> total = escapes_ + 256*minimum; \
(context) -> symbols = 0; \
}
static enet_uint16
enet_symbol_rescale (ENetSymbol * symbol)
{
enet_uint16 total = 0;
for (;;)
{
symbol -> count -= symbol->count >> 1;
symbol -> under = symbol -> count;
if (symbol -> left)
symbol -> under += enet_symbol_rescale (symbol + symbol -> left);
total += symbol -> under;
if (! symbol -> right) break;
symbol += symbol -> right;
}
return total;
}
#define ENET_CONTEXT_RESCALE(context, minimum) \
{ \
(context) -> total = (context) -> symbols ? enet_symbol_rescale ((context) + (context) -> symbols) : 0; \
(context) -> escapes -= (context) -> escapes >> 1; \
(context) -> total += (context) -> escapes + 256*minimum; \
}
#define ENET_RANGE_CODER_OUTPUT(value) \
{ \
if (outData >= outEnd) \
return 0; \
* outData ++ = value; \
}
#define ENET_RANGE_CODER_ENCODE(under, count, total) \
{ \
encodeRange /= (total); \
encodeLow += (under) * encodeRange; \
encodeRange *= (count); \
for (;;) \
{ \
if((encodeLow ^ (encodeLow + encodeRange)) >= ENET_RANGE_CODER_TOP) \
{ \
if(encodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
encodeRange = -encodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
} \
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
encodeRange <<= 8; \
encodeLow <<= 8; \
} \
}
#define ENET_RANGE_CODER_FLUSH \
{ \
while (encodeLow) \
{ \
ENET_RANGE_CODER_OUTPUT (encodeLow >> 24); \
encodeLow <<= 8; \
} \
}
#define ENET_RANGE_CODER_FREE_SYMBOLS \
{ \
if (nextSymbol >= sizeof (rangeCoder -> symbols) / sizeof (ENetSymbol) - ENET_SUBCONTEXT_ORDER ) \
{ \
nextSymbol = 0; \
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM); \
predicted = 0; \
order = 0; \
} \
}
#define ENET_CONTEXT_ENCODE(context, symbol_, value_, under_, count_, update, minimum) \
{ \
under_ = value*minimum; \
count_ = minimum; \
if (! (context) -> symbols) \
{ \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
(context) -> symbols = symbol_ - (context); \
} \
else \
{ \
ENetSymbol * node = (context) + (context) -> symbols; \
for (;;) \
{ \
if (value_ < node -> value) \
{ \
node -> under += update; \
if (node -> left) { node += node -> left; continue; } \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> left = symbol_ - node; \
} \
else \
if (value_ > node -> value) \
{ \
under_ += node -> under; \
if (node -> right) { node += node -> right; continue; } \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> right = symbol_ - node; \
} \
else \
{ \
count_ += node -> count; \
under_ += node -> under - node -> count; \
node -> under += update; \
node -> count += update; \
symbol_ = node; \
} \
break; \
} \
} \
}
#ifdef ENET_CONTEXT_EXCLUSION
static const ENetSymbol emptyContext = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
#define ENET_CONTEXT_WALK(context, body) \
{ \
const ENetSymbol * node = (context) + (context) -> symbols; \
const ENetSymbol * stack [256]; \
size_t stackSize = 0; \
while (node -> left) \
{ \
stack [stackSize ++] = node; \
node += node -> left; \
} \
for (;;) \
{ \
body; \
if (node -> right) \
{ \
node += node -> right; \
while (node -> left) \
{ \
stack [stackSize ++] = node; \
node += node -> left; \
} \
} \
else \
if (stackSize <= 0) \
break; \
else \
node = stack [-- stackSize]; \
} \
}
#define ENET_CONTEXT_ENCODE_EXCLUDE(context, value_, under, total, minimum) \
ENET_CONTEXT_WALK(context, { \
if (node -> value != value_) \
{ \
enet_uint16 parentCount = rangeCoder -> symbols [node -> parent].count + minimum; \
if (node -> value < value_) \
under -= parentCount; \
total -= parentCount; \
} \
})
#endif
size_t
enet_range_coder_compress (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
const enet_uint8 * inData, * inEnd;
enet_uint32 encodeLow = 0, encodeRange = ~0;
ENetSymbol * root;
enet_uint16 predicted = 0;
size_t order = 0, nextSymbol = 0;
if (rangeCoder == NULL || inBufferCount <= 0 || inLimit <= 0)
return 0;
inData = (const enet_uint8 *) inBuffers -> data;
inEnd = & inData [inBuffers -> dataLength];
inBuffers ++;
inBufferCount --;
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
for (;;)
{
ENetSymbol * subcontext, * symbol;
#ifdef ENET_CONTEXT_EXCLUSION
const ENetSymbol * childContext = & emptyContext;
#endif
enet_uint8 value;
enet_uint16 count, under, * parent = & predicted, total;
if (inData >= inEnd)
{
if (inBufferCount <= 0)
break;
inData = (const enet_uint8 *) inBuffers -> data;
inEnd = & inData [inBuffers -> dataLength];
inBuffers ++;
inBufferCount --;
}
value = * inData ++;
for (subcontext = & rangeCoder -> symbols [predicted];
subcontext != root;
#ifdef ENET_CONTEXT_EXCLUSION
childContext = subcontext,
#endif
subcontext = & rangeCoder -> symbols [subcontext -> parent])
{
ENET_CONTEXT_ENCODE (subcontext, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
total = subcontext -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, 0);
#endif
if (count > 0)
{
ENET_RANGE_CODER_ENCODE (subcontext -> escapes + under, count, total);
}
else
{
if (subcontext -> escapes > 0 && subcontext -> escapes < total)
ENET_RANGE_CODER_ENCODE (0, subcontext -> escapes, total);
subcontext -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
subcontext -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
}
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (subcontext, 0);
if (count > 0) goto nextInput;
}
ENET_CONTEXT_ENCODE (root, symbol, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
total = root -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > ENET_SUBCONTEXT_SYMBOL_DELTA + ENET_SUBCONTEXT_ESCAPE_DELTA)
ENET_CONTEXT_ENCODE_EXCLUDE (childContext, value, under, total, ENET_CONTEXT_SYMBOL_MINIMUM);
#endif
ENET_RANGE_CODER_ENCODE (root -> escapes + under, count, total);
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
nextInput:
if (order >= ENET_SUBCONTEXT_ORDER)
predicted = rangeCoder -> symbols [predicted].parent;
else
order ++;
ENET_RANGE_CODER_FREE_SYMBOLS;
}
ENET_RANGE_CODER_FLUSH;
return (size_t) (outData - outStart);
}
#define ENET_RANGE_CODER_SEED \
{ \
if (inData < inEnd) decodeCode |= * inData ++ << 24; \
if (inData < inEnd) decodeCode |= * inData ++ << 16; \
if (inData < inEnd) decodeCode |= * inData ++ << 8; \
if (inData < inEnd) decodeCode |= * inData ++; \
}
#define ENET_RANGE_CODER_READ(total) ((decodeCode - decodeLow) / (decodeRange /= (total)))
#define ENET_RANGE_CODER_DECODE(under, count, total) \
{ \
decodeLow += (under) * decodeRange; \
decodeRange *= (count); \
for (;;) \
{ \
if((decodeLow ^ (decodeLow + decodeRange)) >= ENET_RANGE_CODER_TOP) \
{ \
if(decodeRange >= ENET_RANGE_CODER_BOTTOM) break; \
decodeRange = -decodeLow & (ENET_RANGE_CODER_BOTTOM - 1); \
} \
decodeCode <<= 8; \
if (inData < inEnd) \
decodeCode |= * inData ++; \
decodeRange <<= 8; \
decodeLow <<= 8; \
} \
}
#define ENET_CONTEXT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, createRoot, visitNode, createRight, createLeft) \
{ \
under_ = 0; \
count_ = minimum; \
if (! (context) -> symbols) \
{ \
createRoot; \
} \
else \
{ \
ENetSymbol * node = (context) + (context) -> symbols; \
for (;;) \
{ \
enet_uint16 after = under_ + node -> under + (node -> value + 1)*minimum, before = node -> count + minimum; \
visitNode; \
if (code >= after) \
{ \
under_ += node -> under; \
if (node -> right) { node += node -> right; continue; } \
createRight; \
} \
else \
if (code < after - before) \
{ \
node -> under += update; \
if (node -> left) { node += node -> left; continue; } \
createLeft; \
} \
else \
{ \
value_ = node -> value; \
count_ += node -> count; \
under_ = after - before; \
node -> under += update; \
node -> count += update; \
symbol_ = node; \
} \
break; \
} \
} \
}
#define ENET_CONTEXT_TRY_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, return 0, exclude (node -> value, after, before), return 0, return 0)
#define ENET_CONTEXT_ROOT_DECODE(context, symbol_, code, value_, under_, count_, update, minimum, exclude) \
ENET_CONTEXT_DECODE (context, symbol_, code, value_, under_, count_, update, minimum, \
{ \
value_ = code / minimum; \
under_ = code - code%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
(context) -> symbols = symbol_ - (context); \
}, \
exclude (node -> value, after, before), \
{ \
value_ = node->value + 1 + (code - after)/minimum; \
under_ = code - (code - after)%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> right = symbol_ - node; \
}, \
{ \
value_ = node->value - 1 - (after - before - code - 1)/minimum; \
under_ = code - (after - before - code - 1)%minimum; \
ENET_SYMBOL_CREATE (symbol_, value_, update); \
node -> left = symbol_ - node; \
}) \
#ifdef ENET_CONTEXT_EXCLUSION
typedef struct _ENetExclude
{
enet_uint8 value;
enet_uint16 under;
} ENetExclude;
#define ENET_CONTEXT_DECODE_EXCLUDE(context, total, minimum) \
{ \
enet_uint16 under = 0; \
nextExclude = excludes; \
ENET_CONTEXT_WALK (context, { \
under += rangeCoder -> symbols [node -> parent].count + minimum; \
nextExclude -> value = node -> value; \
nextExclude -> under = under; \
nextExclude ++; \
}); \
total -= under; \
}
#define ENET_CONTEXT_EXCLUDED(value_, after, before) \
{ \
size_t low = 0, high = nextExclude - excludes; \
for(;;) \
{ \
size_t mid = (low + high) >> 1; \
const ENetExclude * exclude = & excludes [mid]; \
if (value_ < exclude -> value) \
{ \
if (low + 1 < high) \
{ \
high = mid; \
continue; \
} \
if (exclude > excludes) \
after -= exclude [-1].under; \
} \
else \
{ \
if (value_ > exclude -> value) \
{ \
if (low + 1 < high) \
{ \
low = mid; \
continue; \
} \
} \
else \
before = 0; \
after -= exclude -> under; \
} \
break; \
} \
}
#endif
#define ENET_CONTEXT_NOT_EXCLUDED(value_, after, before)
size_t
enet_range_coder_decompress (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit)
{
ENetRangeCoder * rangeCoder = (ENetRangeCoder *) context;
enet_uint8 * outStart = outData, * outEnd = & outData [outLimit];
const enet_uint8 * inEnd = & inData [inLimit];
enet_uint32 decodeLow = 0, decodeCode = 0, decodeRange = ~0;
ENetSymbol * root;
enet_uint16 predicted = 0;
size_t order = 0, nextSymbol = 0;
#ifdef ENET_CONTEXT_EXCLUSION
ENetExclude excludes [256];
ENetExclude * nextExclude = excludes;
#endif
if (rangeCoder == NULL || inLimit <= 0)
return 0;
ENET_CONTEXT_CREATE (root, ENET_CONTEXT_ESCAPE_MINIMUM, ENET_CONTEXT_SYMBOL_MINIMUM);
ENET_RANGE_CODER_SEED;
for (;;)
{
ENetSymbol * subcontext, * symbol, * patch;
#ifdef ENET_CONTEXT_EXCLUSION
const ENetSymbol * childContext = & emptyContext;
#endif
enet_uint8 value = 0;
enet_uint16 code, under, count, bottom, * parent = & predicted, total;
for (subcontext = & rangeCoder -> symbols [predicted];
subcontext != root;
#ifdef ENET_CONTEXT_EXCLUSION
childContext = subcontext,
#endif
subcontext = & rangeCoder -> symbols [subcontext -> parent])
{
if (subcontext -> escapes <= 0)
continue;
total = subcontext -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, 0);
#endif
if (subcontext -> escapes >= total)
continue;
code = ENET_RANGE_CODER_READ (total);
if (code < subcontext -> escapes)
{
ENET_RANGE_CODER_DECODE (0, subcontext -> escapes, total);
continue;
}
code -= subcontext -> escapes;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
{
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_EXCLUDED);
}
else
#endif
{
ENET_CONTEXT_TRY_DECODE (subcontext, symbol, code, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0, ENET_CONTEXT_NOT_EXCLUDED);
}
bottom = symbol - rangeCoder -> symbols;
ENET_RANGE_CODER_DECODE (subcontext -> escapes + under, count, total);
subcontext -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || subcontext -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (subcontext, 0);
goto patchContexts;
}
total = root -> total;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
ENET_CONTEXT_DECODE_EXCLUDE (childContext, total, ENET_CONTEXT_SYMBOL_MINIMUM);
#endif
code = ENET_RANGE_CODER_READ (total);
if (code < root -> escapes)
{
ENET_RANGE_CODER_DECODE (0, root -> escapes, total);
break;
}
code -= root -> escapes;
#ifdef ENET_CONTEXT_EXCLUSION
if (childContext -> total > 0)
{
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_EXCLUDED);
}
else
#endif
{
ENET_CONTEXT_ROOT_DECODE (root, symbol, code, value, under, count, ENET_CONTEXT_SYMBOL_DELTA, ENET_CONTEXT_SYMBOL_MINIMUM, ENET_CONTEXT_NOT_EXCLUDED);
}
bottom = symbol - rangeCoder -> symbols;
ENET_RANGE_CODER_DECODE (root -> escapes + under, count, total);
root -> total += ENET_CONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_CONTEXT_SYMBOL_DELTA + ENET_CONTEXT_SYMBOL_MINIMUM || root -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (root, ENET_CONTEXT_SYMBOL_MINIMUM);
patchContexts:
for (patch = & rangeCoder -> symbols [predicted];
patch != subcontext;
patch = & rangeCoder -> symbols [patch -> parent])
{
ENET_CONTEXT_ENCODE (patch, symbol, value, under, count, ENET_SUBCONTEXT_SYMBOL_DELTA, 0);
* parent = symbol - rangeCoder -> symbols;
parent = & symbol -> parent;
if (count <= 0)
{
patch -> escapes += ENET_SUBCONTEXT_ESCAPE_DELTA;
patch -> total += ENET_SUBCONTEXT_ESCAPE_DELTA;
}
patch -> total += ENET_SUBCONTEXT_SYMBOL_DELTA;
if (count > 0xFF - 2*ENET_SUBCONTEXT_SYMBOL_DELTA || patch -> total > ENET_RANGE_CODER_BOTTOM - 0x100)
ENET_CONTEXT_RESCALE (patch, 0);
}
* parent = bottom;
ENET_RANGE_CODER_OUTPUT (value);
if (order >= ENET_SUBCONTEXT_ORDER)
predicted = rangeCoder -> symbols [predicted].parent;
else
order ++;
ENET_RANGE_CODER_FREE_SYMBOLS;
}
return (size_t) (outData - outStart);
}
/** @defgroup host ENet host functions
@{
*/
/** Sets the packet compressor the host should use to the default range coder.
@param host host to enable the range coder for
@returns 0 on success, < 0 on failure
*/
int
enet_host_compress_with_range_coder (ENetHost * host)
{
ENetCompressor compressor;
memset (& compressor, 0, sizeof (compressor));
compressor.context = enet_range_coder_create();
if (compressor.context == NULL)
return -1;
compressor.compress = enet_range_coder_compress;
compressor.decompress = enet_range_coder_decompress;
compressor.destroy = enet_range_coder_destroy;
enet_host_compress (host, & compressor);
return 0;
}
/** @} */
+29
View File
@@ -0,0 +1,29 @@
AC_INIT([libenet], [1.3.18])
AC_CONFIG_SRCDIR([include/enet/enet.h])
AM_INIT_AUTOMAKE([foreign])
AC_CONFIG_MACRO_DIR([m4])
AC_PROG_CC
AC_PROG_LIBTOOL
AC_CHECK_FUNC(getaddrinfo, [AC_DEFINE(HAS_GETADDRINFO)])
AC_CHECK_FUNC(getnameinfo, [AC_DEFINE(HAS_GETNAMEINFO)])
AC_CHECK_FUNC(gethostbyaddr_r, [AC_DEFINE(HAS_GETHOSTBYADDR_R)])
AC_CHECK_FUNC(gethostbyname_r, [AC_DEFINE(HAS_GETHOSTBYNAME_R)])
AC_CHECK_FUNC(poll, [AC_DEFINE(HAS_POLL)])
AC_CHECK_FUNC(fcntl, [AC_DEFINE(HAS_FCNTL)])
AC_CHECK_FUNC(inet_pton, [AC_DEFINE(HAS_INET_PTON)])
AC_CHECK_FUNC(inet_ntop, [AC_DEFINE(HAS_INET_NTOP)])
AC_CHECK_DECLS(offsetof, [AC_DEFINE(HAS_OFFSETOF)], [], [#include <stddef.h>])
AC_CHECK_MEMBER(struct msghdr.msg_flags, [AC_DEFINE(HAS_MSGHDR_FLAGS)], , [#include <sys/socket.h>])
AC_CHECK_TYPE(socklen_t, [AC_DEFINE(HAS_SOCKLEN_T)], ,
#include <sys/types.h>
#include <sys/socket.h>
)
AC_CONFIG_FILES([Makefile
libenet.pc])
AC_OUTPUT
+24
View File
@@ -0,0 +1,24 @@
/**
@page FAQ Frequently Answered Questions
@section Q1 Is ENet thread-safe?
ENet does not use any significant global variables, the vast majority
of state is encapsulated in the ENetHost structure. As such, as long
as the application guards access to this structure, then ENet should
operate fine in a multi-threaded environment.
@section Q2 Isn't ENet just re-inventing TCP?! What's the point?
In a perfect world, that would be true. But as many have found, using
TCP either in lieu of or in conjunction with UDP can lead to all kinds
of nightmares. TCP is a good, solid protocol, however it simply isn't
up to the task of real-time games. Too much of TCP's implementation
dictates a policy that isn't practical for games. If you want to use
TCP, then do so -- this library is for people that either don't want
to use TCP or have tried and ended up being discouraged with the
performance.
*/
+126
View File
@@ -0,0 +1,126 @@
/**
@page Features Features and Architecture
ENet evolved specifically as a UDP networking layer for the
multiplayer first person shooter Cube. Cube necessitated low latency
communication with data sent out very frequently, so TCP was an
unsuitable choice due to its high latency and stream orientation. UDP,
however, lacks many sometimes necessary features from TCP such as
reliability, sequencing, unrestricted packet sizes, and connection
management. So UDP by itself was not suitable as a network protocol
either. No suitable freely available networking libraries existed at
the time of ENet's creation to fill this niche.
UDP and TCP could have been used together in Cube to benefit somewhat
from both of their features, however, the resulting combinations of
protocols still leaves much to be desired. TCP lacks multiple streams
of communication without resorting to opening many sockets and
complicates delineation of packets due to its buffering behavior. UDP
lacks sequencing, connection management, management of bandwidth
resources, and imposes limitations on the size of packets. A
significant investment is required to integrate these two protocols,
and the end result is worse off in features and performance than the
uniform protocol presented by ENet.
ENet thus attempts to address these issues and provide a single,
uniform protocol layered over UDP to the developer with the best
features of UDP and TCP as well as some useful features neither
provide, with a much cleaner integration than any resulting from a
mixture of UDP and TCP.
@section CM Connection Management
ENet provides a simple connection interface over which to communicate
with a foreign host. The liveness of the connection is actively
monitored by pinging the foreign host at frequent intervals, and also
monitors the network conditions from the local host to the foreign
host such as the mean round trip time and packet loss in this fashion.
@section Sequencing Sequencing
Rather than a single byte stream that complicates the delineation of
packets, ENet presents connections as multiple, properly sequenced
packet streams that simplify the transfer of various types of data.
ENet provides sequencing for all packets by assigning to each sent
packet a sequence number that is incremented as packets are sent. ENet
guarantees that no packet with a higher sequence number will be
delivered before a packet with a lower sequence number, thus ensuring
packets are delivered exactly in the order they are sent.
For unreliable packets, ENet will simply discard the lower sequence
number packet if a packet with a higher sequence number has already
been delivered. This allows the packets to be dispatched immediately
as they arrive, and reduce latency of unreliable packets to an
absolute minimum. For reliable packets, if a higher sequence number
packet arrives, but the preceding packets in the sequence have not yet
arrived, ENet will stall delivery of the higher sequence number
packets until its predecessors have arrived.
@section Channels Channels
Since ENet will stall delivery of reliable packets to ensure proper
sequencing, and consequently any packets of higher sequence number
whether reliable or unreliable, in the event the reliable packet's
predecessors have not yet arrived, this can introduce latency into the
delivery of other packets which may not need to be as strictly ordered
with respect to the packet that stalled their delivery.
To combat this latency and reduce the ordering restrictions on
packets, ENet provides multiple channels of communication over a given
connection. Each channel is independently sequenced, and so the
delivery status of a packet in one channel will not stall the delivery
of other packets in another channel.
@section Reliability Reliability
ENet provides optional reliability of packet delivery by ensuring the
foreign host acknowledges receipt of all reliable packets. ENet will
attempt to resend the packet up to a reasonable amount of times, if no
acknowledgement of the packet's receipt happens within a specified
timeout. Retry timeouts are progressive and become more lenient with
every failed attempt to allow for temporary turbulence in network
conditions.
@section FaR Fragmentation and Reassembly
ENet will send and deliver packets regardless of size. Large packets
are fragmented into many smaller packets of suitable size, and
reassembled on the foreign host to recover the original packet for
delivery. The process is entirely transparent to the developer.
@section Aggregation Aggregation
ENet aggregates all protocol commands, including acknowledgements and
packet transfer, into larger protocol packets to ensure the proper
utilization of the connection and to limit the opportunities for
packet loss that might otherwise result in further delivery latency.
@section Adaptability Adaptability
ENet provides an in-flight data window for reliable packets to ensure
connections are not overwhelmed by volumes of packets. It also
provides a static bandwidth allocation mechanism to ensure the total
volume of packets sent and received to a host don't exceed the host's
capabilities. Further, ENet also provides a dynamic throttle that
responds to deviations from normal network connections to rectify
various types of network congestion by further limiting the volume of
packets sent.
@section Portability Portability
ENet works on Windows and any other Unix or Unix-like platform
providing a BSD sockets interface. The library has a small and stable
code base that can easily be extended to support other platforms and
integrates easily. ENet makes no assumptions about the underlying
platform's endianess or word size.
@section Freedom Freedom
ENet demands no royalties and doesn't carry a viral license that would
restrict you in how you might use it in your programs. ENet is
licensed under a short-and-sweet MIT-style license, which gives you
the freedom to do anything you want with it (well, almost anything).
*/
+63
View File
@@ -0,0 +1,63 @@
/**
@page Installation Installation
ENet should be trivially simple to integrate with most applications.
First, make sure you download the latest source distribution at @ref Downloads.
@section Unix Unix-like Operating Systems
If you are using an ENet release, then you should simply be able to build it
by doing the following:
./configure && make && make install
If you obtained the package from github, you must have automake and autoconf
available to generate the build system first by doing the following command
before using the above mentioned build procedure:
autoreconf -vfi
@subsection SolarisBSD Solaris and BSD
When building ENet under Solaris, you must specify the -lsocket and
-lnsl parameters to your compiler to ensure that the sockets library
is linked in.
@section Windows Microsoft Windows
You may simply use the included "enet.lib" or "enet64.lib" static libraries.
However, if you wish to build the library yourself, then the following
instructions apply:
There is an included MSVC 6 project (enet.dsp) which you may use to
build a suitable library file. Alternatively, you may simply drag all
the ENet source files into your main project.
You will have to link to the Winsock2 libraries, so make sure to add
ws2_32.lib and winmm.lib to your library list (Project Settings | Link |
Object/library modules).
@subsection enet.dsp Building with the included enet.dsp
Load the included enet.dsp. MSVC may ask you to convert it if you
are on a newer version of MSVC - just allow the conversion and save
the resulting project as "enet" or similar. After you build this
project, it will output an "enet.lib" file to either the "Debug/"
or "Release/" directory, depending on which configuration you have
selected to build. By default, it should produce "Debug/enet.lib".
You may then copy the resulting "enet.lib" file and the header files
found in the "include/" directory to your other projects and add it to
their library lists. Make sure to also link against "ws2_32.lib" and
"winmm.lib" as described above.
@subsection DLL DLL
If you wish to build ENet as a DLL you must first define ENET_DLL
within the project (Project Settings | C/C++ | Preprocessor |
Preprocessor definitions) or, more invasively, simply define ENET_DLL
at the top of enet.h.
*/
+26
View File
@@ -0,0 +1,26 @@
/**
@page License License
Copyright (c) 2002-2024 Lee Salzman
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+59
View File
@@ -0,0 +1,59 @@
/** @mainpage ENet
ENet's purpose is to provide a relatively thin, simple and robust
network communication layer on top of UDP (User Datagram Protocol).
The primary feature it provides is optional reliable, in-order
delivery of packets.
ENet omits certain higher level networking features such as authentication,
lobbying, server discovery, encryption, or other similar tasks that are
particularly application specific so that the library remains flexible,
portable, and easily embeddable.
@ref Features
@ref Downloads
@ref Installation
@ref Tutorial
@ref MailingList
@ref IRCChannel
@ref FAQ
@ref License
<a class="el" href="usergroup0.html">Documentation</a>
*/
/**
@page Downloads Downloads
You can retrieve the source to ENet by downloading it in either .tar.gz form
or accessing the github distribution directly.
The most recent stable release (1.3.18) can be downloaded <a class="el" href="download/enet-1.3.18.tar.gz">here</a>.
The last release that is protocol compatible with the 1.2 series or earlier (1.2.5) can be downloaded <a class="el" href="download/enet-1.2.5.tar.gz">here</a>.
You can find the most recent ENet source at <a class="el" href="https://github.com/lsalzman/enet">the github repository</a>.
*/
/**
@page MailingList Mailing List
The <a class="el" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">enet-discuss</a> list is for discussion of ENet, including bug reports or feature requests.
*/
/**
@page IRCChannel IRC Channel
Join the \#enet channel on the <a class="el" href="https://libera.chat">Libera Chat IRC network (irc.libera.chat)</a> for real-time discussion about the ENet library.
*/
+366
View File
@@ -0,0 +1,366 @@
/**
@page Tutorial Tutorial
@ref Initialization
@ref CreateServer
@ref CreateClient
@ref ManageHost
@ref SendingPacket
@ref Disconnecting
@ref Connecting
@section Initialization Initialization
You should include the file <enet/enet.h> when using ENet. Do not
include <enet.h> without the directory prefix, as this may cause
file name conflicts on some systems.
Before using ENet, you must call enet_initialize() to initialize the
library. Upon program exit, you should call enet_deinitialize() so
that the library may clean up any used resources.
@code
#include <enet/enet.h>
int
main (int argc, char ** argv)
{
if (enet_initialize () != 0)
{
fprintf (stderr, "An error occurred while initializing ENet.\n");
return EXIT_FAILURE;
}
atexit (enet_deinitialize);
...
...
...
}
@endcode
@section CreateServer Creating an ENet server
Servers in ENet are constructed with enet_host_create(). You must
specify an address on which to receive data and new connections, as
well as the maximum allowable numbers of connected peers. You may
optionally specify the incoming and outgoing bandwidth of the server
in bytes per second so that ENet may try to statically manage
bandwidth resources among connected peers in addition to its dynamic
throttling algorithm; specifying 0 for these two options will cause
ENet to rely entirely upon its dynamic throttling algorithm to manage
bandwidth.
When done with a host, the host may be destroyed with
enet_host_destroy(). All connected peers to the host will be reset,
and the resources used by the host will be freed.
@code
ENetAddress address;
ENetHost * server;
/* Bind the server to the default localhost. */
/* A specific host address can be specified by */
/* enet_address_set_host (& address, "x.x.x.x"); */
address.host = ENET_HOST_ANY;
/* Bind the server to port 1234. */
address.port = 1234;
server = enet_host_create (& address /* the address to bind the server host to */,
32 /* allow up to 32 clients and/or outgoing connections */,
2 /* allow up to 2 channels to be used, 0 and 1 */,
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
if (server == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet server host.\n");
exit (EXIT_FAILURE);
}
...
...
...
enet_host_destroy(server);
@endcode
@section CreateClient Creating an ENet client
Clients in ENet are similarly constructed with enet_host_create() when
no address is specified to bind the host to. Bandwidth may be
specified for the client host as in the above example. The peer count
controls the maximum number of connections to other server hosts that
may be simultaneously open.
@code
ENetHost * client;
client = enet_host_create (NULL /* create a client host */,
1 /* only allow 1 outgoing connection */,
2 /* allow up 2 channels to be used, 0 and 1 */,
0 /* assume any amount of incoming bandwidth */,
0 /* assume any amount of outgoing bandwidth */);
if (client == NULL)
{
fprintf (stderr,
"An error occurred while trying to create an ENet client host.\n");
exit (EXIT_FAILURE);
}
...
...
...
enet_host_destroy(client);
@endcode
@section ManageHost Managing an ENet host
ENet uses a polled event model to notify the programmer of significant
events. ENet hosts are polled for events with enet_host_service(),
where an optional timeout value in milliseconds may be specified to
control how long ENet will poll; if a timeout of 0 is specified,
enet_host_service() will return immediately if there are no events to
dispatch. enet_host_service() will return 1 if an event was dispatched
within the specified timeout.
Beware that most processing of the network with the ENet stack is done
inside enet_host_service(). Both hosts that make up the sides of a connection
must regularly call this function to ensure packets are actually sent and
received. A common symptom of not actively calling enet_host_service()
on both ends is that one side receives events while the other does not.
The best way to schedule this activity to ensure adequate service is, for
example, to call enet_host_service() with a 0 timeout (meaning non-blocking)
at the beginning of every frame in a game loop.
Currently there are only four types of significant events in ENet:
An event of type ENET_EVENT_TYPE_NONE is returned if no event occurred
within the specified time limit. enet_host_service() will return 0
with this event.
An event of type ENET_EVENT_TYPE_CONNECT is returned when either a new client
host has connected to the server host or when an attempt to establish a
connection with a foreign host has succeeded. Only the "peer" field of the
event structure is valid for this event and contains the newly connected peer.
An event of type ENET_EVENT_TYPE_RECEIVE is returned when a packet is received
from a connected peer. The "peer" field contains the peer the packet was
received from, "channelID" is the channel on which the packet was sent, and
"packet" is the packet that was sent. The packet contained in the "packet"
field must be destroyed with enet_packet_destroy() when you are done
inspecting its contents.
An event of type ENET_EVENT_TYPE_DISCONNECT is returned when a connected peer
has either explicitly disconnected or timed out. Only the "peer" field of the
event structure is valid for this event and contains the peer that
disconnected. Only the "data" field of the peer is still valid on a
disconnect event and must be explicitly reset.
@code
ENetEvent event;
/* Wait up to 1000 milliseconds for an event. */
while (enet_host_service (client, & event, 1000) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_CONNECT:
printf ("A new client connected from %x:%u.\n",
event.peer -> address.host,
event.peer -> address.port);
/* Store any relevant client information here. */
event.peer -> data = "Client information";
break;
case ENET_EVENT_TYPE_RECEIVE:
printf ("A packet of length %u containing %s was received from %s on channel %u.\n",
event.packet -> dataLength,
event.packet -> data,
event.peer -> data,
event.channelID);
/* Clean up the packet now that we're done using it. */
enet_packet_destroy (event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
printf ("%s disconnected.\n", event.peer -> data);
/* Reset the peer's client information. */
event.peer -> data = NULL;
}
}
...
...
...
@endcode
@section SendingPacket Sending a packet to an ENet peer
Packets in ENet are created with enet_packet_create(), where the size
of the packet must be specified. Optionally, initial data may be
specified to copy into the packet.
Certain flags may also be supplied to enet_packet_create() to control
various packet features:
ENET_PACKET_FLAG_RELIABLE specifies that the packet must use reliable
delivery. A reliable packet is guaranteed to be delivered, and a
number of retry attempts will be made until an acknowledgement is
received from the foreign host the packet is sent to. If a certain
number of retry attempts is reached without any acknowledgement, ENet
will assume the peer has disconnected and forcefully reset the
connection. If this flag is not specified, the packet is assumed an
unreliable packet, and no retry attempts will be made nor
acknowledgements generated.
A packet may be resized (extended or truncated) with
enet_packet_resize().
A packet is sent to a foreign host with
enet_peer_send(). enet_peer_send() accepts a channel id over which to
send the packet to a given peer. Once the packet is handed over to
ENet with enet_peer_send(), ENet will handle its deallocation and
enet_packet_destroy() should not be used upon it.
One may also use enet_host_broadcast() to send a packet to all
connected peers on a given host over a specified channel id, as with
enet_peer_send().
Queued packets will be sent on a call to enet_host_service().
Alternatively, enet_host_flush() will send out queued packets without
dispatching any events.
@code
/* Create a reliable packet of size 7 containing "packet\0" */
ENetPacket * packet = enet_packet_create ("packet",
strlen ("packet") + 1,
ENET_PACKET_FLAG_RELIABLE);
/* Extend the packet so and append the string "foo", so it now */
/* contains "packetfoo\0" */
enet_packet_resize (packet, strlen ("packetfoo") + 1);
strcpy (& packet -> data [strlen ("packet")], "foo");
/* Send the packet to the peer over channel id 0. */
/* One could also broadcast the packet by */
/* enet_host_broadcast (host, 0, packet); */
enet_peer_send (peer, 0, packet);
...
...
...
/* One could just use enet_host_service() instead. */
enet_host_flush (host);
@endcode
@section Disconnecting Disconnecting an ENet peer
Peers may be gently disconnected with enet_peer_disconnect(). A
disconnect request will be sent to the foreign host, and ENet will
wait for an acknowledgement from the foreign host before finally
disconnecting. An event of type ENET_EVENT_TYPE_DISCONNECT will be
generated once the disconnection succeeds. Normally timeouts apply to
the disconnect acknowledgement, and so if no acknowledgement is
received after a length of time the peer will be forcefully
disconnected.
enet_peer_reset() will forcefully disconnect a peer. The foreign host
will get no notification of a disconnect and will time out on the
foreign host. No event is generated.
@code
ENetEvent event;
enet_peer_disconnect (peer, 0);
/* Allow up to 3 seconds for the disconnect to succeed
* and drop any packets received packets.
*/
while (enet_host_service (client, & event, 3000) > 0)
{
switch (event.type)
{
case ENET_EVENT_TYPE_RECEIVE:
enet_packet_destroy (event.packet);
break;
case ENET_EVENT_TYPE_DISCONNECT:
puts ("Disconnection succeeded.");
return;
...
...
...
}
}
/* We've arrived here, so the disconnect attempt didn't */
/* succeed yet. Force the connection down. */
enet_peer_reset (peer);
...
...
...
@endcode
@section Connecting Connecting to an ENet host
A connection to a foreign host is initiated with enet_host_connect().
It accepts the address of a foreign host to connect to, and the number
of channels that should be allocated for communication. If N channels
are allocated for use, their channel ids will be numbered 0 through
N-1. A peer representing the connection attempt is returned, or NULL
if there were no available peers over which to initiate the
connection. When the connection attempt succeeds, an event of type
ENET_EVENT_TYPE_CONNECT will be generated. If the connection attempt
times out or otherwise fails, an event of type
ENET_EVENT_TYPE_DISCONNECT will be generated.
@code
ENetAddress address;
ENetEvent event;
ENetPeer *peer;
/* Connect to some.server.net:1234. */
enet_address_set_host (& address, "some.server.net");
address.port = 1234;
/* Initiate the connection, allocating the two channels 0 and 1. */
peer = enet_host_connect (client, & address, 2, 0);
if (peer == NULL)
{
fprintf (stderr,
"No available peers for initiating an ENet connection.\n");
exit (EXIT_FAILURE);
}
/* Wait up to 5 seconds for the connection attempt to succeed. */
if (enet_host_service (client, & event, 5000) > 0 &&
event.type == ENET_EVENT_TYPE_CONNECT)
{
puts ("Connection to some.server.net:1234 succeeded.");
...
...
...
}
else
{
/* Either the 5 seconds are up or a disconnect event was */
/* received. Reset the peer in the event the 5 seconds */
/* had run out without any significant event. */
enet_peer_reset (peer);
puts ("Connection to some.server.net:1234 failed.");
}
...
...
...
@endcode
*/
+168
View File
@@ -0,0 +1,168 @@
# Microsoft Developer Studio Project File - Name="enet" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Static Library" 0x0104
CFG=enet - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "enet.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "enet.mak" CFG="enet - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "enet - Win32 Release" (based on "Win32 (x86) Static Library")
!MESSAGE "enet - Win32 Debug" (based on "Win32 (x86) Static Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "enet - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
# ADD CPP /nologo /W3 /O2 /I "include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ELSEIF "$(CFG)" == "enet - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Target_Dir ""
MTL=midl.exe
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
# ADD CPP /nologo /G6 /MTd /W3 /ZI /Od /I "include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /c
# SUBTRACT CPP /YX
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LIB32=link.exe -lib
# ADD BASE LIB32 /nologo
# ADD LIB32 /nologo
!ENDIF
# Begin Target
# Name "enet - Win32 Release"
# Name "enet - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\host.c
# End Source File
# Begin Source File
SOURCE=.\list.c
# End Source File
# Begin Source File
SOURCE=.\callbacks.c
# End Source File
# Begin Source File
SOURCE=.\compress.c
# End Source File
# Begin Source File
SOURCE=.\packet.c
# End Source File
# Begin Source File
SOURCE=.\peer.c
# End Source File
# Begin Source File
SOURCE=.\protocol.c
# End Source File
# Begin Source File
SOURCE=.\unix.c
# End Source File
# Begin Source File
SOURCE=.\win32.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\include\enet\enet.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\list.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\callbacks.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\protocol.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\time.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\types.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\unix.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\utility.h
# End Source File
# Begin Source File
SOURCE=.\include\enet\win32.h
# End Source File
# End Group
# End Target
# End Project
+86
View File
@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
<Option title="enet_dll" />
<Option pch_mode="2" />
<Option compiler="gcc" />
<Build>
<Target title="Debug">
<Option output="bin\Debug\libenet" prefix_auto="1" extension_auto="1" />
<Option object_output="obj\Debug\" />
<Option type="3" />
<Option compiler="gcc" />
<Option createDefFile="1" />
<Option createStaticLib="1" />
<Compiler>
<Add option="-g" />
</Compiler>
</Target>
<Target title="Release">
<Option output="bin\Release\libenet" prefix_auto="1" extension_auto="1" />
<Option object_output="obj\Release\" />
<Option type="3" />
<Option compiler="gcc" />
<Option createDefFile="1" />
<Option createStaticLib="1" />
<Compiler>
<Add option="-O2" />
</Compiler>
<Linker>
<Add option="-s" />
</Linker>
</Target>
</Build>
<Compiler>
<Add option="-Wall" />
<Add option="-DENET_DLL" />
<Add directory="include" />
</Compiler>
<Linker>
<Add library="ws2_32" />
<Add library="Winmm" />
</Linker>
<Unit filename="callbacks.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="compress.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="host.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="include\enet\callbacks.h" />
<Unit filename="include\enet\enet.h" />
<Unit filename="include\enet\list.h" />
<Unit filename="include\enet\protocol.h" />
<Unit filename="include\enet\time.h" />
<Unit filename="include\enet\types.h" />
<Unit filename="include\enet\unix.h" />
<Unit filename="include\enet\utility.h" />
<Unit filename="include\enet\win32.h" />
<Unit filename="list.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="packet.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="peer.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="protocol.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="unix.c">
<Option compilerVar="CC" />
</Unit>
<Unit filename="win32.c">
<Option compilerVar="CC" />
</Unit>
<Extensions>
<code_completion />
<envvars />
<debugger />
</Extensions>
</Project>
</CodeBlocks_project_file>
+503
View File
@@ -0,0 +1,503 @@
/**
@file host.c
@brief ENet host management functions
*/
#define ENET_BUILDING_LIB 1
#include <string.h>
#include "enet/enet.h"
/** @defgroup host ENet host functions
@{
*/
/** Creates a host for communicating to peers.
@param address the address at which other peers may connect to this host. If NULL, then no peers may connect to the host.
@param peerCount the maximum number of peers that should be allocated for the host.
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
@param incomingBandwidth downstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@param outgoingBandwidth upstream bandwidth of the host in bytes/second; if 0, ENet will assume unlimited bandwidth.
@returns the host on success and NULL on failure
@remarks ENet will strategically drop packets on specific sides of a connection between hosts
to ensure the host's bandwidth is not overwhelmed. The bandwidth parameters also determine
the window size of a connection which limits the amount of reliable packets that may be in transit
at any given time.
*/
ENetHost *
enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelLimit, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
ENetHost * host;
ENetPeer * currentPeer;
if (peerCount > ENET_PROTOCOL_MAXIMUM_PEER_ID)
return NULL;
host = (ENetHost *) enet_malloc (sizeof (ENetHost));
if (host == NULL)
return NULL;
memset (host, 0, sizeof (ENetHost));
host -> peers = (ENetPeer *) enet_malloc (peerCount * sizeof (ENetPeer));
if (host -> peers == NULL)
{
enet_free (host);
return NULL;
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));
host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
enet_socket_destroy (host -> socket);
enet_free (host -> peers);
enet_free (host);
return NULL;
}
enet_socket_set_option (host -> socket, ENET_SOCKOPT_NONBLOCK, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_BROADCAST, 1);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_RCVBUF, ENET_HOST_RECEIVE_BUFFER_SIZE);
enet_socket_set_option (host -> socket, ENET_SOCKOPT_SNDBUF, ENET_HOST_SEND_BUFFER_SIZE);
if (address != NULL && enet_socket_get_address (host -> socket, & host -> address) < 0)
host -> address = * address;
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
else
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
host -> randomSeed = (enet_uint32) (size_t) host;
host -> randomSeed += enet_host_random_seed ();
host -> randomSeed = (host -> randomSeed << 16) | (host -> randomSeed >> 16);
host -> channelLimit = channelLimit;
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> bandwidthThrottleEpoch = 0;
host -> recalculateBandwidthLimits = 0;
host -> mtu = ENET_HOST_DEFAULT_MTU;
host -> peerCount = peerCount;
host -> commandCount = 0;
host -> bufferCount = 0;
host -> checksum = NULL;
host -> receivedAddress.host = ENET_HOST_ANY;
host -> receivedAddress.port = 0;
host -> receivedData = NULL;
host -> receivedDataLength = 0;
host -> totalSentData = 0;
host -> totalSentPackets = 0;
host -> totalReceivedData = 0;
host -> totalReceivedPackets = 0;
host -> totalQueued = 0;
host -> connectedPeers = 0;
host -> bandwidthLimitedPeers = 0;
host -> duplicatePeers = ENET_PROTOCOL_MAXIMUM_PEER_ID;
host -> maximumPacketSize = ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE;
host -> maximumWaitingData = ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA;
host -> compressor.context = NULL;
host -> compressor.compress = NULL;
host -> compressor.decompress = NULL;
host -> compressor.destroy = NULL;
host -> intercept = NULL;
enet_list_clear (& host -> dispatchQueue);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
currentPeer -> host = host;
currentPeer -> incomingPeerID = currentPeer - host -> peers;
currentPeer -> outgoingSessionID = currentPeer -> incomingSessionID = 0xFF;
currentPeer -> data = NULL;
enet_list_clear (& currentPeer -> acknowledgements);
enet_list_clear (& currentPeer -> sentReliableCommands);
enet_list_clear (& currentPeer -> outgoingCommands);
enet_list_clear (& currentPeer -> outgoingSendReliableCommands);
enet_list_clear (& currentPeer -> dispatchedCommands);
enet_peer_reset (currentPeer);
}
return host;
}
/** Destroys the host and all resources associated with it.
@param host pointer to the host to destroy
*/
void
enet_host_destroy (ENetHost * host)
{
ENetPeer * currentPeer;
if (host == NULL)
return;
enet_socket_destroy (host -> socket);
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
enet_peer_reset (currentPeer);
}
if (host -> compressor.context != NULL && host -> compressor.destroy)
(* host -> compressor.destroy) (host -> compressor.context);
enet_free (host -> peers);
enet_free (host);
}
enet_uint32
enet_host_random (ENetHost * host)
{
/* Mulberry32 by Tommy Ettinger */
enet_uint32 n = (host -> randomSeed += 0x6D2B79F5U);
n = (n ^ (n >> 15)) * (n | 1U);
n ^= n + (n ^ (n >> 7)) * (n | 61U);
return n ^ (n >> 14);
}
/** Initiates a connection to a foreign host.
@param host host seeking the connection
@param address destination for the connection
@param channelCount number of channels to allocate
@param data user data supplied to the receiving host
@returns a peer representing the foreign host on success, NULL on failure
@remarks The peer returned will have not completed the connection until enet_host_service()
notifies of an ENET_EVENT_TYPE_CONNECT event for the peer.
*/
ENetPeer *
enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelCount, enet_uint32 data)
{
ENetPeer * currentPeer;
ENetChannel * channel;
ENetProtocol command;
if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
else
if (channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelCount = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
break;
}
if (currentPeer >= & host -> peers [host -> peerCount])
return NULL;
currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
if (currentPeer -> channels == NULL)
return NULL;
currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
currentPeer -> address = * address;
currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
if (host -> outgoingBandwidth == 0)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
else
currentPeer -> windowSize = (host -> outgoingBandwidth /
ENET_PEER_WINDOW_SIZE_SCALE) *
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
else
if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
for (channel = currentPeer -> channels;
channel < & currentPeer -> channels [channelCount];
++ channel)
{
channel -> outgoingReliableSequenceNumber = 0;
channel -> outgoingUnreliableSequenceNumber = 0;
channel -> incomingReliableSequenceNumber = 0;
channel -> incomingUnreliableSequenceNumber = 0;
enet_list_clear (& channel -> incomingReliableCommands);
enet_list_clear (& channel -> incomingUnreliableCommands);
channel -> usedReliableWindows = 0;
memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
}
command.header.command = ENET_PROTOCOL_COMMAND_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.connect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
command.connect.incomingSessionID = currentPeer -> incomingSessionID;
command.connect.outgoingSessionID = currentPeer -> outgoingSessionID;
command.connect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
command.connect.windowSize = ENET_HOST_TO_NET_32 (currentPeer -> windowSize);
command.connect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
command.connect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
command.connect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
command.connect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
command.connect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
command.connect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
command.connect.connectID = currentPeer -> connectID;
command.connect.data = ENET_HOST_TO_NET_32 (data);
enet_peer_queue_outgoing_command (currentPeer, & command, NULL, 0, 0);
return currentPeer;
}
/** Queues a packet to be sent to all peers associated with the host.
@param host host on which to broadcast the packet
@param channelID channel on which to broadcast
@param packet packet to broadcast
*/
void
enet_host_broadcast (ENetHost * host, enet_uint8 channelID, ENetPacket * packet)
{
ENetPeer * currentPeer;
for (currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
continue;
enet_peer_send (currentPeer, channelID, packet);
}
if (packet -> referenceCount == 0)
enet_packet_destroy (packet);
}
/** Sets the packet compressor the host should use to compress and decompress packets.
@param host host to enable or disable compression for
@param compressor callbacks for for the packet compressor; if NULL, then compression is disabled
*/
void
enet_host_compress (ENetHost * host, const ENetCompressor * compressor)
{
if (host -> compressor.context != NULL && host -> compressor.destroy)
(* host -> compressor.destroy) (host -> compressor.context);
if (compressor)
host -> compressor = * compressor;
else
host -> compressor.context = NULL;
}
/** Limits the maximum allowed channels of future incoming connections.
@param host host to limit
@param channelLimit the maximum number of channels allowed; if 0, then this is equivalent to ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT
*/
void
enet_host_channel_limit (ENetHost * host, size_t channelLimit)
{
if (! channelLimit || channelLimit > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT;
else
if (channelLimit < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT)
channelLimit = ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT;
host -> channelLimit = channelLimit;
}
/** Adjusts the bandwidth limits of a host.
@param host host to adjust
@param incomingBandwidth new incoming bandwidth
@param outgoingBandwidth new outgoing bandwidth
@remarks the incoming and outgoing bandwidth parameters are identical in function to those
specified in enet_host_create().
*/
void
enet_host_bandwidth_limit (ENetHost * host, enet_uint32 incomingBandwidth, enet_uint32 outgoingBandwidth)
{
host -> incomingBandwidth = incomingBandwidth;
host -> outgoingBandwidth = outgoingBandwidth;
host -> recalculateBandwidthLimits = 1;
}
void
enet_host_bandwidth_throttle (ENetHost * host)
{
enet_uint32 timeCurrent = enet_time_get (),
elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
peersRemaining = (enet_uint32) host -> connectedPeers,
dataTotal = ~0,
bandwidth = ~0,
throttle = 0,
bandwidthLimit = 0;
int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0;
ENetPeer * peer;
ENetProtocol command;
if (elapsedTime < ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
return;
host -> bandwidthThrottleEpoch = timeCurrent;
if (peersRemaining == 0)
return;
if (host -> outgoingBandwidth != 0)
{
dataTotal = 0;
bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
dataTotal += peer -> outgoingDataTotal;
}
}
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
if (dataTotal <= bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
enet_uint32 peerBandwidth;
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidth == 0 ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peerBandwidth = (peer -> incomingBandwidth * elapsedTime) / 1000;
if ((throttle * peer -> outgoingDataTotal) / ENET_PEER_PACKET_THROTTLE_SCALE <= peerBandwidth)
continue;
peer -> packetThrottleLimit = (peerBandwidth *
ENET_PEER_PACKET_THROTTLE_SCALE) / peer -> outgoingDataTotal;
if (peer -> packetThrottleLimit == 0)
peer -> packetThrottleLimit = 1;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> outgoingBandwidthThrottleEpoch = timeCurrent;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peerBandwidth;
dataTotal -= peerBandwidth;
}
}
if (peersRemaining > 0)
{
if (dataTotal <= bandwidth)
throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
else
throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> outgoingBandwidthThrottleEpoch == timeCurrent)
continue;
peer -> packetThrottleLimit = throttle;
if (peer -> packetThrottle > peer -> packetThrottleLimit)
peer -> packetThrottle = peer -> packetThrottleLimit;
peer -> incomingDataTotal = 0;
peer -> outgoingDataTotal = 0;
}
}
if (host -> recalculateBandwidthLimits)
{
host -> recalculateBandwidthLimits = 0;
peersRemaining = (enet_uint32) host -> connectedPeers;
bandwidth = host -> incomingBandwidth;
needsAdjustment = 1;
if (bandwidth == 0)
bandwidthLimit = 0;
else
while (peersRemaining > 0 && needsAdjustment != 0)
{
needsAdjustment = 0;
bandwidthLimit = bandwidth / peersRemaining;
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if ((peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER) ||
peer -> incomingBandwidthThrottleEpoch == timeCurrent)
continue;
if (peer -> outgoingBandwidth > 0 &&
peer -> outgoingBandwidth >= bandwidthLimit)
continue;
peer -> incomingBandwidthThrottleEpoch = timeCurrent;
needsAdjustment = 1;
-- peersRemaining;
bandwidth -= peer -> outgoingBandwidth;
}
}
for (peer = host -> peers;
peer < & host -> peers [host -> peerCount];
++ peer)
{
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
continue;
command.header.command = ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
command.header.channelID = 0xFF;
command.bandwidthLimit.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
if (peer -> incomingBandwidthThrottleEpoch == timeCurrent)
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (peer -> outgoingBandwidth);
else
command.bandwidthLimit.incomingBandwidth = ENET_HOST_TO_NET_32 (bandwidthLimit);
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
}
}
}
/** @} */
+37
View File
@@ -0,0 +1,37 @@
/**
@file callbacks.h
@brief ENet callbacks
*/
#ifndef __ENET_CALLBACKS_H__
#define __ENET_CALLBACKS_H__
#include <stdlib.h>
typedef struct _ENetCallbacks
{
void * (ENET_CALLBACK * malloc) (size_t size);
void (ENET_CALLBACK * free) (void * memory);
void (ENET_CALLBACK * no_memory) (void);
} ENetCallbacks;
#ifdef __cplusplus
extern "C"
{
#endif
/** @defgroup callbacks ENet internal callbacks
@{
@ingroup private
*/
extern void * enet_malloc (size_t);
extern void enet_free (void *);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* __ENET_CALLBACKS_H__ */
+615
View File
@@ -0,0 +1,615 @@
/**
@file enet.h
@brief ENet public header file
*/
#ifndef __ENET_ENET_H__
#define __ENET_ENET_H__
#include <stdlib.h>
#ifdef _WIN32
#include "enet/win32.h"
#else
#include "enet/unix.h"
#endif
#include "enet/types.h"
#include "enet/protocol.h"
#include "enet/list.h"
#include "enet/callbacks.h"
#define ENET_VERSION_MAJOR 1
#define ENET_VERSION_MINOR 3
#define ENET_VERSION_PATCH 18
#define ENET_VERSION_CREATE(major, minor, patch) (((major)<<16) | ((minor)<<8) | (patch))
#define ENET_VERSION_GET_MAJOR(version) (((version)>>16)&0xFF)
#define ENET_VERSION_GET_MINOR(version) (((version)>>8)&0xFF)
#define ENET_VERSION_GET_PATCH(version) ((version)&0xFF)
#define ENET_VERSION ENET_VERSION_CREATE(ENET_VERSION_MAJOR, ENET_VERSION_MINOR, ENET_VERSION_PATCH)
typedef enet_uint32 ENetVersion;
struct _ENetHost;
struct _ENetEvent;
struct _ENetPacket;
typedef enum _ENetSocketType
{
ENET_SOCKET_TYPE_STREAM = 1,
ENET_SOCKET_TYPE_DATAGRAM = 2
} ENetSocketType;
typedef enum _ENetSocketWait
{
ENET_SOCKET_WAIT_NONE = 0,
ENET_SOCKET_WAIT_SEND = (1 << 0),
ENET_SOCKET_WAIT_RECEIVE = (1 << 1),
ENET_SOCKET_WAIT_INTERRUPT = (1 << 2)
} ENetSocketWait;
typedef enum _ENetSocketOption
{
ENET_SOCKOPT_NONBLOCK = 1,
ENET_SOCKOPT_BROADCAST = 2,
ENET_SOCKOPT_RCVBUF = 3,
ENET_SOCKOPT_SNDBUF = 4,
ENET_SOCKOPT_REUSEADDR = 5,
ENET_SOCKOPT_RCVTIMEO = 6,
ENET_SOCKOPT_SNDTIMEO = 7,
ENET_SOCKOPT_ERROR = 8,
ENET_SOCKOPT_NODELAY = 9,
ENET_SOCKOPT_TTL = 10
} ENetSocketOption;
typedef enum _ENetSocketShutdown
{
ENET_SOCKET_SHUTDOWN_READ = 0,
ENET_SOCKET_SHUTDOWN_WRITE = 1,
ENET_SOCKET_SHUTDOWN_READ_WRITE = 2
} ENetSocketShutdown;
#define ENET_HOST_ANY 0
#define ENET_HOST_BROADCAST 0xFFFFFFFFU
#define ENET_PORT_ANY 0
/**
* Portable internet address structure.
*
* The host must be specified in network byte-order, and the port must be in host
* byte-order. The constant ENET_HOST_ANY may be used to specify the default
* server host. The constant ENET_HOST_BROADCAST may be used to specify the
* broadcast address (255.255.255.255). This makes sense for enet_host_connect,
* but not for enet_host_create. Once a server responds to a broadcast, the
* address is updated from ENET_HOST_BROADCAST to the server's actual IP address.
*/
typedef struct _ENetAddress
{
enet_uint32 host;
enet_uint16 port;
} ENetAddress;
/**
* Packet flag bit constants.
*
* The host must be specified in network byte-order, and the port must be in
* host byte-order. The constant ENET_HOST_ANY may be used to specify the
* default server host.
@sa ENetPacket
*/
typedef enum _ENetPacketFlag
{
/** packet must be received by the target peer and resend attempts should be
* made until the packet is delivered */
ENET_PACKET_FLAG_RELIABLE = (1 << 0),
/** packet will not be sequenced with other packets
*/
ENET_PACKET_FLAG_UNSEQUENCED = (1 << 1),
/** packet will not allocate data, and user must supply it instead */
ENET_PACKET_FLAG_NO_ALLOCATE = (1 << 2),
/** packet will be fragmented using unreliable (instead of reliable) sends
* if it exceeds the MTU */
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT = (1 << 3),
/** whether the packet has been sent from all queues it has been entered into */
ENET_PACKET_FLAG_SENT = (1<<8)
} ENetPacketFlag;
typedef void (ENET_CALLBACK * ENetPacketFreeCallback) (struct _ENetPacket *);
/**
* ENet packet structure.
*
* An ENet data packet that may be sent to or received from a peer. The shown
* fields should only be read and never modified. The data field contains the
* allocated data for the packet. The dataLength fields specifies the length
* of the allocated data. The flags field is either 0 (specifying no flags),
* or a bitwise-or of any combination of the following flags:
*
* ENET_PACKET_FLAG_RELIABLE - packet must be received by the target peer
* and resend attempts should be made until the packet is delivered
*
* ENET_PACKET_FLAG_UNSEQUENCED - packet will not be sequenced with other packets
* (not supported for reliable packets)
*
* ENET_PACKET_FLAG_NO_ALLOCATE - packet will not allocate data, and user must supply it instead
*
* ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT - packet will be fragmented using unreliable
* (instead of reliable) sends if it exceeds the MTU
*
* ENET_PACKET_FLAG_SENT - whether the packet has been sent from all queues it has been entered into
@sa ENetPacketFlag
*/
typedef struct _ENetPacket
{
size_t referenceCount; /**< internal use only */
enet_uint32 flags; /**< bitwise-or of ENetPacketFlag constants */
enet_uint8 * data; /**< allocated data for packet */
size_t dataLength; /**< length of data */
ENetPacketFreeCallback freeCallback; /**< function to be called when the packet is no longer in use */
void * userData; /**< application private data, may be freely modified */
} ENetPacket;
typedef struct _ENetAcknowledgement
{
ENetListNode acknowledgementList;
enet_uint32 sentTime;
ENetProtocol command;
} ENetAcknowledgement;
typedef struct _ENetOutgoingCommand
{
ENetListNode outgoingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
enet_uint32 sentTime;
enet_uint32 roundTripTimeout;
enet_uint32 queueTime;
enet_uint32 fragmentOffset;
enet_uint16 fragmentLength;
enet_uint16 sendAttempts;
ENetProtocol command;
ENetPacket * packet;
} ENetOutgoingCommand;
typedef struct _ENetIncomingCommand
{
ENetListNode incomingCommandList;
enet_uint16 reliableSequenceNumber;
enet_uint16 unreliableSequenceNumber;
ENetProtocol command;
enet_uint32 fragmentCount;
enet_uint32 fragmentsRemaining;
enet_uint32 * fragments;
ENetPacket * packet;
} ENetIncomingCommand;
typedef enum _ENetPeerState
{
ENET_PEER_STATE_DISCONNECTED = 0,
ENET_PEER_STATE_CONNECTING = 1,
ENET_PEER_STATE_ACKNOWLEDGING_CONNECT = 2,
ENET_PEER_STATE_CONNECTION_PENDING = 3,
ENET_PEER_STATE_CONNECTION_SUCCEEDED = 4,
ENET_PEER_STATE_CONNECTED = 5,
ENET_PEER_STATE_DISCONNECT_LATER = 6,
ENET_PEER_STATE_DISCONNECTING = 7,
ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT = 8,
ENET_PEER_STATE_ZOMBIE = 9
} ENetPeerState;
#ifndef ENET_BUFFER_MAXIMUM
#define ENET_BUFFER_MAXIMUM (1 + 2 * ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS)
#endif
enum
{
ENET_HOST_RECEIVE_BUFFER_SIZE = 256 * 1024,
ENET_HOST_SEND_BUFFER_SIZE = 256 * 1024,
ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL = 1000,
ENET_HOST_DEFAULT_MTU = 1392,
ENET_HOST_DEFAULT_MAXIMUM_PACKET_SIZE = 32 * 1024 * 1024,
ENET_HOST_DEFAULT_MAXIMUM_WAITING_DATA = 32 * 1024 * 1024,
ENET_PEER_DEFAULT_ROUND_TRIP_TIME = 500,
ENET_PEER_DEFAULT_PACKET_THROTTLE = 32,
ENET_PEER_PACKET_THROTTLE_SCALE = 32,
ENET_PEER_PACKET_THROTTLE_COUNTER = 7,
ENET_PEER_PACKET_THROTTLE_ACCELERATION = 2,
ENET_PEER_PACKET_THROTTLE_DECELERATION = 2,
ENET_PEER_PACKET_THROTTLE_INTERVAL = 5000,
ENET_PEER_PACKET_LOSS_SCALE = (1 << 16),
ENET_PEER_PACKET_LOSS_INTERVAL = 10000,
ENET_PEER_WINDOW_SIZE_SCALE = 64 * 1024,
ENET_PEER_TIMEOUT_LIMIT = 32,
ENET_PEER_TIMEOUT_MINIMUM = 5000,
ENET_PEER_TIMEOUT_MAXIMUM = 30000,
ENET_PEER_PING_INTERVAL = 500,
ENET_PEER_UNSEQUENCED_WINDOWS = 64,
ENET_PEER_UNSEQUENCED_WINDOW_SIZE = 1024,
ENET_PEER_FREE_UNSEQUENCED_WINDOWS = 32,
ENET_PEER_RELIABLE_WINDOWS = 16,
ENET_PEER_RELIABLE_WINDOW_SIZE = 0x1000,
ENET_PEER_FREE_RELIABLE_WINDOWS = 8
};
typedef struct _ENetChannel
{
enet_uint16 outgoingReliableSequenceNumber;
enet_uint16 outgoingUnreliableSequenceNumber;
enet_uint16 usedReliableWindows;
enet_uint16 reliableWindows [ENET_PEER_RELIABLE_WINDOWS];
enet_uint16 incomingReliableSequenceNumber;
enet_uint16 incomingUnreliableSequenceNumber;
ENetList incomingReliableCommands;
ENetList incomingUnreliableCommands;
} ENetChannel;
typedef enum _ENetPeerFlag
{
ENET_PEER_FLAG_NEEDS_DISPATCH = (1 << 0),
ENET_PEER_FLAG_CONTINUE_SENDING = (1 << 1)
} ENetPeerFlag;
/**
* An ENet peer which data packets may be sent or received from.
*
* No fields should be modified unless otherwise specified.
*/
typedef struct _ENetPeer
{
ENetListNode dispatchList;
struct _ENetHost * host;
enet_uint16 outgoingPeerID;
enet_uint16 incomingPeerID;
enet_uint32 connectID;
enet_uint8 outgoingSessionID;
enet_uint8 incomingSessionID;
ENetAddress address; /**< Internet address of the peer */
void * data; /**< Application private data, may be freely modified */
ENetPeerState state;
ENetChannel * channels;
size_t channelCount; /**< Number of channels allocated for communication with peer */
enet_uint32 incomingBandwidth; /**< Downstream bandwidth of the client in bytes/second */
enet_uint32 outgoingBandwidth; /**< Upstream bandwidth of the client in bytes/second */
enet_uint32 incomingBandwidthThrottleEpoch;
enet_uint32 outgoingBandwidthThrottleEpoch;
enet_uint32 incomingDataTotal;
enet_uint32 outgoingDataTotal;
enet_uint32 lastSendTime;
enet_uint32 lastReceiveTime;
enet_uint32 nextTimeout;
enet_uint32 earliestTimeout;
enet_uint32 packetLossEpoch;
enet_uint32 packetsSent;
enet_uint32 packetsLost;
enet_uint32 packetLoss; /**< mean packet loss of reliable packets as a ratio with respect to the constant ENET_PEER_PACKET_LOSS_SCALE */
enet_uint32 packetLossVariance;
enet_uint32 packetThrottle;
enet_uint32 packetThrottleLimit;
enet_uint32 packetThrottleCounter;
enet_uint32 packetThrottleEpoch;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 packetThrottleInterval;
enet_uint32 pingInterval;
enet_uint32 timeoutLimit;
enet_uint32 timeoutMinimum;
enet_uint32 timeoutMaximum;
enet_uint32 lastRoundTripTime;
enet_uint32 lowestRoundTripTime;
enet_uint32 lastRoundTripTimeVariance;
enet_uint32 highestRoundTripTimeVariance;
enet_uint32 roundTripTime; /**< mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement */
enet_uint32 roundTripTimeVariance;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 reliableDataInTransit;
enet_uint16 outgoingReliableSequenceNumber;
ENetList acknowledgements;
ENetList sentReliableCommands;
ENetList outgoingSendReliableCommands;
ENetList outgoingCommands;
ENetList dispatchedCommands;
enet_uint16 flags;
enet_uint16 reserved;
enet_uint16 incomingUnsequencedGroup;
enet_uint16 outgoingUnsequencedGroup;
enet_uint32 unsequencedWindow [ENET_PEER_UNSEQUENCED_WINDOW_SIZE / 32];
enet_uint32 eventData;
size_t totalWaitingData;
} ENetPeer;
/** An ENet packet compressor for compressing UDP packets before socket sends or receives.
*/
typedef struct _ENetCompressor
{
/** Context data for the compressor. Must be non-NULL. */
void * context;
/** Compresses from inBuffers[0:inBufferCount-1], containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
size_t (ENET_CALLBACK * compress) (void * context, const ENetBuffer * inBuffers, size_t inBufferCount, size_t inLimit, enet_uint8 * outData, size_t outLimit);
/** Decompresses from inData, containing inLimit bytes, to outData, outputting at most outLimit bytes. Should return 0 on failure. */
size_t (ENET_CALLBACK * decompress) (void * context, const enet_uint8 * inData, size_t inLimit, enet_uint8 * outData, size_t outLimit);
/** Destroys the context when compression is disabled or the host is destroyed. May be NULL. */
void (ENET_CALLBACK * destroy) (void * context);
} ENetCompressor;
/** Callback that computes the checksum of the data held in buffers[0:bufferCount-1] */
typedef enet_uint32 (ENET_CALLBACK * ENetChecksumCallback) (const ENetBuffer * buffers, size_t bufferCount);
/** Callback for intercepting received raw UDP packets. Should return 1 to intercept, 0 to ignore, or -1 to propagate an error. */
typedef int (ENET_CALLBACK * ENetInterceptCallback) (struct _ENetHost * host, struct _ENetEvent * event);
/** An ENet host for communicating with peers.
*
* No fields should be modified unless otherwise stated.
@sa enet_host_create()
@sa enet_host_destroy()
@sa enet_host_connect()
@sa enet_host_service()
@sa enet_host_flush()
@sa enet_host_broadcast()
@sa enet_host_compress()
@sa enet_host_compress_with_range_coder()
@sa enet_host_channel_limit()
@sa enet_host_bandwidth_limit()
@sa enet_host_bandwidth_throttle()
*/
typedef struct _ENetHost
{
ENetSocket socket;
ENetAddress address; /**< Internet address of the host */
enet_uint32 incomingBandwidth; /**< downstream bandwidth of the host */
enet_uint32 outgoingBandwidth; /**< upstream bandwidth of the host */
enet_uint32 bandwidthThrottleEpoch;
enet_uint32 mtu;
enet_uint32 randomSeed;
int recalculateBandwidthLimits;
ENetPeer * peers; /**< array of peers allocated for this host */
size_t peerCount; /**< number of peers allocated for this host */
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime;
ENetList dispatchQueue;
enet_uint32 totalQueued;
size_t packetSize;
enet_uint16 headerFlags;
ENetProtocol commands [ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS];
size_t commandCount;
ENetBuffer buffers [ENET_BUFFER_MAXIMUM];
size_t bufferCount;
ENetChecksumCallback checksum; /**< callback the user can set to enable packet checksums for this host */
ENetCompressor compressor;
enet_uint8 packetData [2][ENET_PROTOCOL_MAXIMUM_MTU];
ENetAddress receivedAddress;
enet_uint8 * receivedData;
size_t receivedDataLength;
enet_uint32 totalSentData; /**< total data sent, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalSentPackets; /**< total UDP packets sent, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalReceivedData; /**< total data received, user should reset to 0 as needed to prevent overflow */
enet_uint32 totalReceivedPackets; /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
ENetInterceptCallback intercept; /**< callback the user can set to intercept received raw UDP packets */
size_t connectedPeers;
size_t bandwidthLimitedPeers;
size_t duplicatePeers; /**< optional number of allowed peers from duplicate IPs, defaults to ENET_PROTOCOL_MAXIMUM_PEER_ID */
size_t maximumPacketSize; /**< the maximum allowable packet size that may be sent or received on a peer */
size_t maximumWaitingData; /**< the maximum aggregate amount of buffer space a peer may use waiting for packets to be delivered */
} ENetHost;
/**
* An ENet event type, as specified in @ref ENetEvent.
*/
typedef enum _ENetEventType
{
/** no event occurred within the specified time limit */
ENET_EVENT_TYPE_NONE = 0,
/** a connection request initiated by enet_host_connect has completed.
* The peer field contains the peer which successfully connected.
*/
ENET_EVENT_TYPE_CONNECT = 1,
/** a peer has disconnected. This event is generated on a successful
* completion of a disconnect initiated by enet_peer_disconnect, if
* a peer has timed out, or if a connection request intialized by
* enet_host_connect has timed out. The peer field contains the peer
* which disconnected. The data field contains user supplied data
* describing the disconnection, or 0, if none is available.
*/
ENET_EVENT_TYPE_DISCONNECT = 2,
/** a packet has been received from a peer. The peer field specifies the
* peer which sent the packet. The channelID field specifies the channel
* number upon which the packet was received. The packet field contains
* the packet that was received; this packet must be destroyed with
* enet_packet_destroy after use.
*/
ENET_EVENT_TYPE_RECEIVE = 3
} ENetEventType;
/**
* An ENet event as returned by enet_host_service().
@sa enet_host_service
*/
typedef struct _ENetEvent
{
ENetEventType type; /**< type of the event */
ENetPeer * peer; /**< peer that generated a connect, disconnect or receive event */
enet_uint8 channelID; /**< channel on the peer that generated the event, if appropriate */
enet_uint32 data; /**< data associated with the event, if appropriate */
ENetPacket * packet; /**< packet associated with the event, if appropriate */
} ENetEvent;
#ifdef __cplusplus
extern "C"
{
#endif
/** @defgroup global ENet global functions
@{
*/
/**
Initializes ENet globally. Must be called prior to using any functions in
ENet.
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize (void);
/**
Initializes ENet globally and supplies user-overridden callbacks. Must be called prior to using any functions in ENet. Do not use enet_initialize() if you use this variant. Make sure the ENetCallbacks structure is zeroed out so that any additional callbacks added in future versions will be properly ignored.
@param version the constant ENET_VERSION should be supplied so ENet knows which version of ENetCallbacks struct to use
@param inits user-overridden callbacks where any NULL callbacks will use ENet's defaults
@returns 0 on success, < 0 on failure
*/
ENET_API int enet_initialize_with_callbacks (ENetVersion version, const ENetCallbacks * inits);
/**
Shuts down ENet globally. Should be called when a program that has
initialized ENet exits.
*/
ENET_API void enet_deinitialize (void);
/**
Gives the linked version of the ENet library.
@returns the version number
*/
ENET_API ENetVersion enet_linked_version (void);
/** @} */
/** @defgroup private ENet private implementation functions */
/**
Returns the wall-time in milliseconds. Its initial value is unspecified
unless otherwise set.
*/
ENET_API enet_uint32 enet_time_get (void);
/**
Sets the current wall-time in milliseconds.
*/
ENET_API void enet_time_set (enet_uint32);
/** @defgroup socket ENet socket functions
@{
*/
ENET_API ENetSocket enet_socket_create (ENetSocketType);
ENET_API int enet_socket_bind (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_get_address (ENetSocket, ENetAddress *);
ENET_API int enet_socket_listen (ENetSocket, int);
ENET_API ENetSocket enet_socket_accept (ENetSocket, ENetAddress *);
ENET_API int enet_socket_connect (ENetSocket, const ENetAddress *);
ENET_API int enet_socket_send (ENetSocket, const ENetAddress *, const ENetBuffer *, size_t);
ENET_API int enet_socket_receive (ENetSocket, ENetAddress *, ENetBuffer *, size_t);
ENET_API int enet_socket_wait (ENetSocket, enet_uint32 *, enet_uint32);
ENET_API int enet_socket_set_option (ENetSocket, ENetSocketOption, int);
ENET_API int enet_socket_get_option (ENetSocket, ENetSocketOption, int *);
ENET_API int enet_socket_shutdown (ENetSocket, ENetSocketShutdown);
ENET_API void enet_socket_destroy (ENetSocket);
ENET_API int enet_socketset_select (ENetSocket, ENetSocketSet *, ENetSocketSet *, enet_uint32);
/** @} */
/** @defgroup Address ENet address functions
@{
*/
/** Attempts to parse the printable form of the IP address in the parameter hostName
and sets the host field in the address parameter if successful.
@param address destination to store the parsed IP address
@param hostName IP address to parse
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host_ip (ENetAddress * address, const char * hostName);
/** Attempts to resolve the host named by the parameter hostName and sets
the host field in the address parameter if successful.
@param address destination to store resolved address
@param hostName host name to lookup
@retval 0 on success
@retval < 0 on failure
@returns the address of the given hostName in address on success
*/
ENET_API int enet_address_set_host (ENetAddress * address, const char * hostName);
/** Gives the printable form of the IP address specified in the address parameter.
@param address address printed
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host_ip (const ENetAddress * address, char * hostName, size_t nameLength);
/** Attempts to do a reverse lookup of the host field in the address parameter.
@param address address used for reverse lookup
@param hostName destination for name, must not be NULL
@param nameLength maximum length of hostName.
@returns the null-terminated name of the host in hostName on success
@retval 0 on success
@retval < 0 on failure
*/
ENET_API int enet_address_get_host (const ENetAddress * address, char * hostName, size_t nameLength);
/** @} */
ENET_API ENetPacket * enet_packet_create (const void *, size_t, enet_uint32);
ENET_API void enet_packet_destroy (ENetPacket *);
ENET_API int enet_packet_resize (ENetPacket *, size_t);
ENET_API enet_uint32 enet_crc32 (const ENetBuffer *, size_t);
ENET_API ENetHost * enet_host_create (const ENetAddress *, size_t, size_t, enet_uint32, enet_uint32);
ENET_API void enet_host_destroy (ENetHost *);
ENET_API ENetPeer * enet_host_connect (ENetHost *, const ENetAddress *, size_t, enet_uint32);
ENET_API int enet_host_check_events (ENetHost *, ENetEvent *);
ENET_API int enet_host_service (ENetHost *, ENetEvent *, enet_uint32);
ENET_API void enet_host_flush (ENetHost *);
ENET_API void enet_host_broadcast (ENetHost *, enet_uint8, ENetPacket *);
ENET_API void enet_host_compress (ENetHost *, const ENetCompressor *);
ENET_API int enet_host_compress_with_range_coder (ENetHost * host);
ENET_API void enet_host_channel_limit (ENetHost *, size_t);
ENET_API void enet_host_bandwidth_limit (ENetHost *, enet_uint32, enet_uint32);
extern void enet_host_bandwidth_throttle (ENetHost *);
extern enet_uint32 enet_host_random_seed (void);
extern enet_uint32 enet_host_random (ENetHost *);
ENET_API int enet_peer_send (ENetPeer *, enet_uint8, ENetPacket *);
ENET_API ENetPacket * enet_peer_receive (ENetPeer *, enet_uint8 * channelID);
ENET_API void enet_peer_ping (ENetPeer *);
ENET_API void enet_peer_ping_interval (ENetPeer *, enet_uint32);
ENET_API void enet_peer_timeout (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
ENET_API void enet_peer_reset (ENetPeer *);
ENET_API void enet_peer_disconnect (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_now (ENetPeer *, enet_uint32);
ENET_API void enet_peer_disconnect_later (ENetPeer *, enet_uint32);
ENET_API void enet_peer_throttle_configure (ENetPeer *, enet_uint32, enet_uint32, enet_uint32);
extern int enet_peer_throttle (ENetPeer *, enet_uint32);
extern void enet_peer_reset_queues (ENetPeer *);
extern int enet_peer_has_outgoing_commands (ENetPeer *);
extern void enet_peer_setup_outgoing_command (ENetPeer *, ENetOutgoingCommand *);
extern ENetOutgoingCommand * enet_peer_queue_outgoing_command (ENetPeer *, const ENetProtocol *, ENetPacket *, enet_uint32, enet_uint16);
extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const ENetProtocol *, const void *, size_t, enet_uint32, enet_uint32);
extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
extern void enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_on_connect (ENetPeer *);
extern void enet_peer_on_disconnect (ENetPeer *);
ENET_API void * enet_range_coder_create (void);
ENET_API void enet_range_coder_destroy (void *);
ENET_API size_t enet_range_coder_compress (void *, const ENetBuffer *, size_t, size_t, enet_uint8 *, size_t);
ENET_API size_t enet_range_coder_decompress (void *, const enet_uint8 *, size_t, enet_uint8 *, size_t);
extern size_t enet_protocol_command_size (enet_uint8);
#ifdef __cplusplus
}
#endif
#endif /* __ENET_ENET_H__ */
+52
View File
@@ -0,0 +1,52 @@
/**
@file list.h
@brief ENet list management
*/
#ifndef __ENET_LIST_H__
#define __ENET_LIST_H__
#include <stdlib.h>
typedef struct _ENetListNode
{
struct _ENetListNode * next;
struct _ENetListNode * previous;
} ENetListNode;
typedef ENetListNode * ENetListIterator;
typedef struct _ENetList
{
ENetListNode sentinel;
} ENetList;
#ifdef __cplusplus
extern "C"
{
#endif
extern void enet_list_clear (ENetList *);
extern ENetListIterator enet_list_insert (ENetListIterator, void *);
extern void * enet_list_remove (ENetListIterator);
extern ENetListIterator enet_list_move (ENetListIterator, void *, void *);
extern size_t enet_list_size (ENetList *);
#ifdef __cplusplus
}
#endif
#define enet_list_begin(list) ((list) -> sentinel.next)
#define enet_list_end(list) (& (list) -> sentinel)
#define enet_list_empty(list) (enet_list_begin (list) == enet_list_end (list))
#define enet_list_next(iterator) ((iterator) -> next)
#define enet_list_previous(iterator) ((iterator) -> previous)
#define enet_list_front(list) ((void *) (list) -> sentinel.next)
#define enet_list_back(list) ((void *) (list) -> sentinel.previous)
#endif /* __ENET_LIST_H__ */
+198
View File
@@ -0,0 +1,198 @@
/**
@file protocol.h
@brief ENet protocol
*/
#ifndef __ENET_PROTOCOL_H__
#define __ENET_PROTOCOL_H__
#include "enet/types.h"
enum
{
ENET_PROTOCOL_MINIMUM_MTU = 576,
ENET_PROTOCOL_MAXIMUM_MTU = 4096,
ENET_PROTOCOL_MAXIMUM_PACKET_COMMANDS = 32,
ENET_PROTOCOL_MINIMUM_WINDOW_SIZE = 4096,
ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE = 65536,
ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT = 1,
ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT = 255,
ENET_PROTOCOL_MAXIMUM_PEER_ID = 0xFFF,
ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT = 1024 * 1024
};
typedef enum _ENetProtocolCommand
{
ENET_PROTOCOL_COMMAND_NONE = 0,
ENET_PROTOCOL_COMMAND_ACKNOWLEDGE = 1,
ENET_PROTOCOL_COMMAND_CONNECT = 2,
ENET_PROTOCOL_COMMAND_VERIFY_CONNECT = 3,
ENET_PROTOCOL_COMMAND_DISCONNECT = 4,
ENET_PROTOCOL_COMMAND_PING = 5,
ENET_PROTOCOL_COMMAND_SEND_RELIABLE = 6,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE = 7,
ENET_PROTOCOL_COMMAND_SEND_FRAGMENT = 8,
ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED = 9,
ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT = 10,
ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE = 11,
ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT = 12,
ENET_PROTOCOL_COMMAND_COUNT = 13,
ENET_PROTOCOL_COMMAND_MASK = 0x0F
} ENetProtocolCommand;
typedef enum _ENetProtocolFlag
{
ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE = (1 << 7),
ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED = (1 << 6),
ENET_PROTOCOL_HEADER_FLAG_COMPRESSED = (1 << 14),
ENET_PROTOCOL_HEADER_FLAG_SENT_TIME = (1 << 15),
ENET_PROTOCOL_HEADER_FLAG_MASK = ENET_PROTOCOL_HEADER_FLAG_COMPRESSED | ENET_PROTOCOL_HEADER_FLAG_SENT_TIME,
ENET_PROTOCOL_HEADER_SESSION_MASK = (3 << 12),
ENET_PROTOCOL_HEADER_SESSION_SHIFT = 12
} ENetProtocolFlag;
#ifdef _MSC_VER
#pragma pack(push, 1)
#define ENET_PACKED
#elif defined(__GNUC__) || defined(__clang__)
#define ENET_PACKED __attribute__ ((packed))
#else
#define ENET_PACKED
#endif
typedef struct _ENetProtocolHeader
{
enet_uint16 peerID;
enet_uint16 sentTime;
} ENET_PACKED ENetProtocolHeader;
typedef struct _ENetProtocolCommandHeader
{
enet_uint8 command;
enet_uint8 channelID;
enet_uint16 reliableSequenceNumber;
} ENET_PACKED ENetProtocolCommandHeader;
typedef struct _ENetProtocolAcknowledge
{
ENetProtocolCommandHeader header;
enet_uint16 receivedReliableSequenceNumber;
enet_uint16 receivedSentTime;
} ENET_PACKED ENetProtocolAcknowledge;
typedef struct _ENetProtocolConnect
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint8 incomingSessionID;
enet_uint8 outgoingSessionID;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 connectID;
enet_uint32 data;
} ENET_PACKED ENetProtocolConnect;
typedef struct _ENetProtocolVerifyConnect
{
ENetProtocolCommandHeader header;
enet_uint16 outgoingPeerID;
enet_uint8 incomingSessionID;
enet_uint8 outgoingSessionID;
enet_uint32 mtu;
enet_uint32 windowSize;
enet_uint32 channelCount;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
enet_uint32 connectID;
} ENET_PACKED ENetProtocolVerifyConnect;
typedef struct _ENetProtocolBandwidthLimit
{
ENetProtocolCommandHeader header;
enet_uint32 incomingBandwidth;
enet_uint32 outgoingBandwidth;
} ENET_PACKED ENetProtocolBandwidthLimit;
typedef struct _ENetProtocolThrottleConfigure
{
ENetProtocolCommandHeader header;
enet_uint32 packetThrottleInterval;
enet_uint32 packetThrottleAcceleration;
enet_uint32 packetThrottleDeceleration;
} ENET_PACKED ENetProtocolThrottleConfigure;
typedef struct _ENetProtocolDisconnect
{
ENetProtocolCommandHeader header;
enet_uint32 data;
} ENET_PACKED ENetProtocolDisconnect;
typedef struct _ENetProtocolPing
{
ENetProtocolCommandHeader header;
} ENET_PACKED ENetProtocolPing;
typedef struct _ENetProtocolSendReliable
{
ENetProtocolCommandHeader header;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendReliable;
typedef struct _ENetProtocolSendUnreliable
{
ENetProtocolCommandHeader header;
enet_uint16 unreliableSequenceNumber;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendUnreliable;
typedef struct _ENetProtocolSendUnsequenced
{
ENetProtocolCommandHeader header;
enet_uint16 unsequencedGroup;
enet_uint16 dataLength;
} ENET_PACKED ENetProtocolSendUnsequenced;
typedef struct _ENetProtocolSendFragment
{
ENetProtocolCommandHeader header;
enet_uint16 startSequenceNumber;
enet_uint16 dataLength;
enet_uint32 fragmentCount;
enet_uint32 fragmentNumber;
enet_uint32 totalLength;
enet_uint32 fragmentOffset;
} ENET_PACKED ENetProtocolSendFragment;
typedef union _ENetProtocol
{
ENetProtocolCommandHeader header;
ENetProtocolAcknowledge acknowledge;
ENetProtocolConnect connect;
ENetProtocolVerifyConnect verifyConnect;
ENetProtocolDisconnect disconnect;
ENetProtocolPing ping;
ENetProtocolSendReliable sendReliable;
ENetProtocolSendUnreliable sendUnreliable;
ENetProtocolSendUnsequenced sendUnsequenced;
ENetProtocolSendFragment sendFragment;
ENetProtocolBandwidthLimit bandwidthLimit;
ENetProtocolThrottleConfigure throttleConfigure;
} ENET_PACKED ENetProtocol;
#ifdef _MSC_VER
#pragma pack(pop)
#endif
#endif /* __ENET_PROTOCOL_H__ */
+18
View File
@@ -0,0 +1,18 @@
/**
@file time.h
@brief ENet time constants and macros
*/
#ifndef __ENET_TIME_H__
#define __ENET_TIME_H__
#define ENET_TIME_OVERFLOW 86400000
#define ENET_TIME_LESS(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_GREATER(a, b) ((b) - (a) >= ENET_TIME_OVERFLOW)
#define ENET_TIME_LESS_EQUAL(a, b) (! ENET_TIME_GREATER (a, b))
#define ENET_TIME_GREATER_EQUAL(a, b) (! ENET_TIME_LESS (a, b))
#define ENET_TIME_DIFFERENCE(a, b) ((a) - (b) >= ENET_TIME_OVERFLOW ? (b) - (a) : (a) - (b))
#endif /* __ENET_TIME_H__ */
+13
View File
@@ -0,0 +1,13 @@
/**
@file types.h
@brief type definitions for ENet
*/
#ifndef __ENET_TYPES_H__
#define __ENET_TYPES_H__
typedef unsigned char enet_uint8; /**< unsigned 8-bit type */
typedef unsigned short enet_uint16; /**< unsigned 16-bit type */
typedef unsigned int enet_uint32; /**< unsigned 32-bit type */
#endif /* __ENET_TYPES_H__ */
+48
View File
@@ -0,0 +1,48 @@
/**
@file unix.h
@brief ENet Unix header
*/
#ifndef __ENET_UNIX_H__
#define __ENET_UNIX_H__
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#ifdef MSG_MAXIOVLEN
#define ENET_BUFFER_MAXIMUM MSG_MAXIOVLEN
#endif
typedef int ENetSocket;
#define ENET_SOCKET_NULL -1
#define ENET_HOST_TO_NET_16(value) (htons (value)) /**< macro that converts host to net byte-order of a 16-bit value */
#define ENET_HOST_TO_NET_32(value) (htonl (value)) /**< macro that converts host to net byte-order of a 32-bit value */
#define ENET_NET_TO_HOST_16(value) (ntohs (value)) /**< macro that converts net to host byte-order of a 16-bit value */
#define ENET_NET_TO_HOST_32(value) (ntohl (value)) /**< macro that converts net to host byte-order of a 32-bit value */
typedef struct
{
void * data;
size_t dataLength;
} ENetBuffer;
#define ENET_CALLBACK
#define ENET_API extern
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_UNIX_H__ */
+23
View File
@@ -0,0 +1,23 @@
/**
@file utility.h
@brief ENet utility header
*/
#ifndef __ENET_UTILITY_H__
#define __ENET_UTILITY_H__
#ifdef HAS_OFFSETOF
#include <stddef.h>
#endif
#define ENET_MAX(x, y) ((x) > (y) ? (x) : (y))
#define ENET_MIN(x, y) ((x) < (y) ? (x) : (y))
#define ENET_DIFFERENCE(x, y) ((x) < (y) ? (y) - (x) : (x) - (y))
#ifdef HAS_OFFSETOF
#define ENET_OFFSETOF(str, field) (offsetof(str, field))
#else
#define ENET_OFFSETOF(str, field) ((size_t) & ((str *) 0) -> field)
#endif
#endif /* __ENET_UTILITY_H__ */
+63
View File
@@ -0,0 +1,63 @@
/**
@file win32.h
@brief ENet Win32 header
*/
#ifndef __ENET_WIN32_H__
#define __ENET_WIN32_H__
#ifdef _MSC_VER
#ifdef ENET_BUILDING_LIB
#pragma warning (disable: 4267) // size_t to int conversion
#pragma warning (disable: 4244) // 64bit to 32bit int
#pragma warning (disable: 4018) // signed/unsigned mismatch
#pragma warning (disable: 4146) // unary minus operator applied to unsigned type
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif
#ifndef _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#endif
#endif
#endif
#include <stdlib.h>
#include <winsock2.h>
typedef SOCKET ENetSocket;
#define ENET_SOCKET_NULL INVALID_SOCKET
#define ENET_HOST_TO_NET_16(value) (htons (value))
#define ENET_HOST_TO_NET_32(value) (htonl (value))
#define ENET_NET_TO_HOST_16(value) (ntohs (value))
#define ENET_NET_TO_HOST_32(value) (ntohl (value))
typedef struct
{
size_t dataLength;
void * data;
} ENetBuffer;
#define ENET_CALLBACK __cdecl
#ifdef ENET_DLL
#ifdef ENET_BUILDING_LIB
#define ENET_API __declspec( dllexport )
#else
#define ENET_API __declspec( dllimport )
#endif /* ENET_BUILDING_LIB */
#else /* !ENET_DLL */
#define ENET_API extern
#endif /* ENET_DLL */
typedef fd_set ENetSocketSet;
#define ENET_SOCKETSET_EMPTY(sockset) FD_ZERO (& (sockset))
#define ENET_SOCKETSET_ADD(sockset, socket) FD_SET (socket, & (sockset))
#define ENET_SOCKETSET_REMOVE(sockset, socket) FD_CLR (socket, & (sockset))
#define ENET_SOCKETSET_CHECK(sockset, socket) FD_ISSET (socket, & (sockset))
#endif /* __ENET_WIN32_H__ */
+10
View File
@@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: @PACKAGE_NAME@
Description: Low-latency UDP networking library supporting optional reliability
Version: @PACKAGE_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lenet
+75
View File
@@ -0,0 +1,75 @@
/**
@file list.c
@brief ENet linked list functions
*/
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/**
@defgroup list ENet linked list utility functions
@ingroup private
@{
*/
void
enet_list_clear (ENetList * list)
{
list -> sentinel.next = & list -> sentinel;
list -> sentinel.previous = & list -> sentinel;
}
ENetListIterator
enet_list_insert (ENetListIterator position, void * data)
{
ENetListIterator result = (ENetListIterator) data;
result -> previous = position -> previous;
result -> next = position;
result -> previous -> next = result;
position -> previous = result;
return result;
}
void *
enet_list_remove (ENetListIterator position)
{
position -> previous -> next = position -> next;
position -> next -> previous = position -> previous;
return position;
}
ENetListIterator
enet_list_move (ENetListIterator position, void * dataFirst, void * dataLast)
{
ENetListIterator first = (ENetListIterator) dataFirst,
last = (ENetListIterator) dataLast;
first -> previous -> next = last -> next;
last -> next -> previous = first -> previous;
first -> previous = position -> previous;
last -> next = position;
first -> previous -> next = first;
position -> previous = last;
return first;
}
size_t
enet_list_size (ENetList * list)
{
size_t size = 0;
ENetListIterator position;
for (position = enet_list_begin (list);
position != enet_list_end (list);
position = enet_list_next (position))
++ size;
return size;
}
/** @} */
View File
+163
View File
@@ -0,0 +1,163 @@
/**
@file packet.c
@brief ENet packet management functions
*/
#include <string.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
/** @defgroup Packet ENet packet functions
@{
*/
/** Creates a packet that may be sent to a peer.
@param data initial contents of the packet's data; the packet's data will remain uninitialized if data is NULL.
@param dataLength size of the data allocated for this packet
@param flags flags for this packet as described for the ENetPacket structure.
@returns the packet on success, NULL on failure
*/
ENetPacket *
enet_packet_create (const void * data, size_t dataLength, enet_uint32 flags)
{
ENetPacket * packet = (ENetPacket *) enet_malloc (sizeof (ENetPacket));
if (packet == NULL)
return NULL;
if (flags & ENET_PACKET_FLAG_NO_ALLOCATE)
packet -> data = (enet_uint8 *) data;
else
if (dataLength <= 0)
packet -> data = NULL;
else
{
packet -> data = (enet_uint8 *) enet_malloc (dataLength);
if (packet -> data == NULL)
{
enet_free (packet);
return NULL;
}
if (data != NULL)
memcpy (packet -> data, data, dataLength);
}
packet -> referenceCount = 0;
packet -> flags = flags;
packet -> dataLength = dataLength;
packet -> freeCallback = NULL;
packet -> userData = NULL;
return packet;
}
/** Destroys the packet and deallocates its data.
@param packet packet to be destroyed
*/
void
enet_packet_destroy (ENetPacket * packet)
{
if (packet == NULL)
return;
if (packet -> freeCallback != NULL)
(* packet -> freeCallback) (packet);
if (! (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE) &&
packet -> data != NULL)
enet_free (packet -> data);
enet_free (packet);
}
/** Attempts to resize the data in the packet to length specified in the
dataLength parameter
@param packet packet to resize
@param dataLength new size for the packet data
@returns 0 on success, < 0 on failure
*/
int
enet_packet_resize (ENetPacket * packet, size_t dataLength)
{
enet_uint8 * newData;
if (dataLength <= packet -> dataLength || (packet -> flags & ENET_PACKET_FLAG_NO_ALLOCATE))
{
packet -> dataLength = dataLength;
return 0;
}
newData = (enet_uint8 *) enet_malloc (dataLength);
if (newData == NULL)
return -1;
if (packet -> data != NULL)
{
if (packet -> dataLength > 0)
memcpy (newData, packet -> data, packet -> dataLength);
enet_free (packet -> data);
}
packet -> data = newData;
packet -> dataLength = dataLength;
return 0;
}
static const enet_uint32 crcTable [256] =
{
0, 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, 0x5005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0xBDBDF21,
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
};
enet_uint32
enet_crc32 (const ENetBuffer * buffers, size_t bufferCount)
{
enet_uint32 crc = 0xFFFFFFFF;
while (bufferCount -- > 0)
{
const enet_uint8 * data = (const enet_uint8 *) buffers -> data,
* dataEnd = & data [buffers -> dataLength];
while (data < dataEnd)
{
crc = (crc >> 8) ^ crcTable [(crc & 0xFF) ^ *data++];
}
++ buffers;
}
return ENET_HOST_TO_NET_32 (~ crc);
}
/** @} */
+1030
View File
File diff suppressed because it is too large Load Diff
+59
View File
@@ -0,0 +1,59 @@
solution "enet"
configurations { "Debug", "Release" }
platforms { "x32", "x64" }
project "enet_static"
kind "StaticLib"
language "C"
files { "*.c" }
includedirs { "include/" }
configuration "Debug"
targetsuffix "d"
defines({ "DEBUG" })
flags { "Symbols" }
configuration "Release"
defines({ "NDEBUG" })
flags { "Optimize" }
configuration { "Debug", "x64" }
targetsuffix "64d"
configuration { "Release", "x64" }
targetsuffix "64"
project "enet"
kind "SharedLib"
language "C"
files { "*.c" }
includedirs { "include/" }
defines({"ENET_DLL=1" })
configuration "Debug"
targetsuffix "d"
defines({ "DEBUG" })
flags { "Symbols" }
configuration "Release"
defines({ "NDEBUG" })
flags { "Optimize" }
configuration { "Debug", "x64" }
targetsuffix "64d"
configuration { "Release", "x64" }
targetsuffix "64"
+1921
View File
File diff suppressed because it is too large Load Diff
+630
View File
@@ -0,0 +1,630 @@
/**
@file unix.c
@brief ENet Unix system specific functions
*/
#ifndef _WIN32
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#ifdef __APPLE__
#ifdef HAS_POLL
#undef HAS_POLL
#endif
#ifndef HAS_FCNTL
#define HAS_FCNTL 1
#endif
#ifndef HAS_INET_PTON
#define HAS_INET_PTON 1
#endif
#ifndef HAS_INET_NTOP
#define HAS_INET_NTOP 1
#endif
#ifndef HAS_MSGHDR_FLAGS
#define HAS_MSGHDR_FLAGS 1
#endif
#ifndef HAS_SOCKLEN_T
#define HAS_SOCKLEN_T 1
#endif
#ifndef HAS_GETADDRINFO
#define HAS_GETADDRINFO 1
#endif
#ifndef HAS_GETNAMEINFO
#define HAS_GETNAMEINFO 1
#endif
#endif
#ifdef HAS_FCNTL
#include <fcntl.h>
#endif
#ifdef HAS_POLL
#include <poll.h>
#endif
#if !defined(HAS_SOCKLEN_T) && !defined(__socklen_t_defined)
typedef int socklen_t;
#endif
#ifndef MSG_NOSIGNAL
#define MSG_NOSIGNAL 0
#endif
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
return 0;
}
void
enet_deinitialize (void)
{
}
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) time (NULL);
}
enet_uint32
enet_time_get (void)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
return timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
struct timeval timeVal;
gettimeofday (& timeVal, NULL);
timeBase = timeVal.tv_sec * 1000 + timeVal.tv_usec / 1000 - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
#ifdef HAS_INET_PTON
if (! inet_pton (AF_INET, name, & address -> host))
#else
if (! inet_aton (name, (struct in_addr *) & address -> host))
#endif
return -1;
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
#ifdef HAS_GETADDRINFO
struct addrinfo hints, * resultList = NULL, * result = NULL;
memset (& hints, 0, sizeof (hints));
hints.ai_family = AF_INET;
if (getaddrinfo (name, NULL, NULL, & resultList) != 0)
return -1;
for (result = resultList; result != NULL; result = result -> ai_next)
{
if (result -> ai_family == AF_INET && result -> ai_addr != NULL && result -> ai_addrlen >= sizeof (struct sockaddr_in))
{
struct sockaddr_in * sin = (struct sockaddr_in *) result -> ai_addr;
address -> host = sin -> sin_addr.s_addr;
freeaddrinfo (resultList);
return 0;
}
}
if (resultList != NULL)
freeaddrinfo (resultList);
#else
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYNAME_R
struct hostent hostData;
char buffer [2048];
int errnum;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyname_r (name, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
hostEntry = gethostbyname (name);
#endif
if (hostEntry != NULL && hostEntry -> h_addrtype == AF_INET)
{
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
#endif
return enet_address_set_host_ip (address, name);
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_INET_NTOP
if (inet_ntop (AF_INET, & address -> host, name, nameLength) == NULL)
#else
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr != NULL)
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
else
#endif
return -1;
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
#ifdef HAS_GETNAMEINFO
struct sockaddr_in sin;
int err;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
err = getnameinfo ((struct sockaddr *) & sin, sizeof (sin), name, nameLength, NULL, 0, NI_NAMEREQD);
if (! err)
{
if (name != NULL && nameLength > 0 && ! memchr (name, '\0', nameLength))
return -1;
return 0;
}
if (err != EAI_NONAME)
return -1;
#else
struct in_addr in;
struct hostent * hostEntry = NULL;
#ifdef HAS_GETHOSTBYADDR_R
struct hostent hostData;
char buffer [2048];
int errnum;
in.s_addr = address -> host;
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__GNU__)
gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & hostEntry, & errnum);
#else
hostEntry = gethostbyaddr_r ((char *) & in, sizeof (struct in_addr), AF_INET, & hostData, buffer, sizeof (buffer), & errnum);
#endif
#else
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
#endif
if (hostEntry != NULL)
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
return 0;
}
#endif
return enet_address_get_host_ip (address, name, nameLength);
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in));
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog);
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = -1;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
#ifdef HAS_FCNTL
result = fcntl (socket, F_SETFL, (value ? O_NONBLOCK : 0) | (fcntl (socket, F_GETFL) & ~O_NONBLOCK));
#else
result = ioctl (socket, FIONBIO, & value);
#endif
break;
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVTIMEO:
{
struct timeval timeVal;
timeVal.tv_sec = value / 1000;
timeVal.tv_usec = (value % 1000) * 1000;
result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & timeVal, sizeof (struct timeval));
break;
}
case ENET_SOCKOPT_SNDTIMEO:
{
struct timeval timeVal;
timeVal.tv_sec = value / 1000;
timeVal.tv_usec = (value % 1000) * 1000;
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & timeVal, sizeof (struct timeval));
break;
}
case ENET_SOCKOPT_NODELAY:
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == -1 ? -1 : 0;
}
int
enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
{
int result = -1;
socklen_t len;
switch (option)
{
case ENET_SOCKOPT_ERROR:
len = sizeof (int);
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof (int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
return result == -1 ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
if (result == -1 && errno == EINPROGRESS)
return 0;
return result;
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
int result;
struct sockaddr_in sin;
socklen_t sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == -1)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
int
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
{
return shutdown (socket, (int) how);
}
void
enet_socket_destroy (ENetSocket socket)
{
if (socket != -1)
close (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int sentLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
sentLength = sendmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (sentLength == -1)
{
if (errno == EWOULDBLOCK)
return 0;
return -1;
}
return sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
struct msghdr msgHdr;
struct sockaddr_in sin;
int recvLength;
memset (& msgHdr, 0, sizeof (struct msghdr));
if (address != NULL)
{
msgHdr.msg_name = & sin;
msgHdr.msg_namelen = sizeof (struct sockaddr_in);
}
msgHdr.msg_iov = (struct iovec *) buffers;
msgHdr.msg_iovlen = bufferCount;
recvLength = recvmsg (socket, & msgHdr, MSG_NOSIGNAL);
if (recvLength == -1)
{
switch (errno)
{
case EWOULDBLOCK:
return 0;
case EINTR:
case EMSGSIZE:
return -2;
default:
return -1;
}
}
#ifdef HAS_MSGHDR_FLAGS
if (msgHdr.msg_flags & MSG_TRUNC)
return -2;
#endif
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
#ifdef HAS_POLL
struct pollfd pollSocket;
int pollCount;
pollSocket.fd = socket;
pollSocket.events = 0;
if (* condition & ENET_SOCKET_WAIT_SEND)
pollSocket.events |= POLLOUT;
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
pollSocket.events |= POLLIN;
pollCount = poll (& pollSocket, 1, timeout);
if (pollCount < 0)
{
if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
{
* condition = ENET_SOCKET_WAIT_INTERRUPT;
return 0;
}
return -1;
}
* condition = ENET_SOCKET_WAIT_NONE;
if (pollCount == 0)
return 0;
if (pollSocket.revents & POLLOUT)
* condition |= ENET_SOCKET_WAIT_SEND;
if (pollSocket.revents & POLLIN)
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#else
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
{
if (errno == EINTR && * condition & ENET_SOCKET_WAIT_INTERRUPT)
{
* condition = ENET_SOCKET_WAIT_INTERRUPT;
return 0;
}
return -1;
}
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
#endif
}
#endif
+455
View File
@@ -0,0 +1,455 @@
/**
@file win32.c
@brief ENet Win32 system specific functions
*/
#ifdef _WIN32
#define ENET_BUILDING_LIB 1
#include "enet/enet.h"
#include <windows.h>
#include <mmsystem.h>
#include <ws2tcpip.h>
static enet_uint32 timeBase = 0;
int
enet_initialize (void)
{
WORD versionRequested = MAKEWORD (1, 1);
WSADATA wsaData;
if (WSAStartup (versionRequested, & wsaData))
return -1;
if (LOBYTE (wsaData.wVersion) != 1||
HIBYTE (wsaData.wVersion) != 1)
{
WSACleanup ();
return -1;
}
timeBeginPeriod (1);
return 0;
}
void
enet_deinitialize (void)
{
timeEndPeriod (1);
WSACleanup ();
}
enet_uint32
enet_host_random_seed (void)
{
return (enet_uint32) timeGetTime ();
}
enet_uint32
enet_time_get (void)
{
return (enet_uint32) timeGetTime () - timeBase;
}
void
enet_time_set (enet_uint32 newTimeBase)
{
timeBase = (enet_uint32) timeGetTime () - newTimeBase;
}
int
enet_address_set_host_ip (ENetAddress * address, const char * name)
{
enet_uint8 vals [4] = { 0, 0, 0, 0 };
int i;
for (i = 0; i < 4; ++ i)
{
const char * next = name + 1;
if (* name != '0')
{
long val = strtol (name, (char **) & next, 10);
if (val < 0 || val > 255 || next == name || next - name > 3)
return -1;
vals [i] = (enet_uint8) val;
}
if (* next != (i < 3 ? '.' : '\0'))
return -1;
name = next + 1;
}
memcpy (& address -> host, vals, sizeof (enet_uint32));
return 0;
}
int
enet_address_set_host (ENetAddress * address, const char * name)
{
struct hostent * hostEntry;
hostEntry = gethostbyname (name);
if (hostEntry == NULL ||
hostEntry -> h_addrtype != AF_INET)
return enet_address_set_host_ip (address, name);
address -> host = * (enet_uint32 *) hostEntry -> h_addr_list [0];
return 0;
}
int
enet_address_get_host_ip (const ENetAddress * address, char * name, size_t nameLength)
{
char * addr = inet_ntoa (* (struct in_addr *) & address -> host);
if (addr == NULL)
return -1;
else
{
size_t addrLen = strlen(addr);
if (addrLen >= nameLength)
return -1;
memcpy (name, addr, addrLen + 1);
}
return 0;
}
int
enet_address_get_host (const ENetAddress * address, char * name, size_t nameLength)
{
struct in_addr in;
struct hostent * hostEntry;
in.s_addr = address -> host;
hostEntry = gethostbyaddr ((char *) & in, sizeof (struct in_addr), AF_INET);
if (hostEntry == NULL)
return enet_address_get_host_ip (address, name, nameLength);
else
{
size_t hostLen = strlen (hostEntry -> h_name);
if (hostLen >= nameLength)
return -1;
memcpy (name, hostEntry -> h_name, hostLen + 1);
}
return 0;
}
int
enet_socket_bind (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
if (address != NULL)
{
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
else
{
sin.sin_port = 0;
sin.sin_addr.s_addr = INADDR_ANY;
}
return bind (socket,
(struct sockaddr *) & sin,
sizeof (struct sockaddr_in)) == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_get_address (ENetSocket socket, ENetAddress * address)
{
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
if (getsockname (socket, (struct sockaddr *) & sin, & sinLength) == -1)
return -1;
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
return 0;
}
int
enet_socket_listen (ENetSocket socket, int backlog)
{
return listen (socket, backlog < 0 ? SOMAXCONN : backlog) == SOCKET_ERROR ? -1 : 0;
}
ENetSocket
enet_socket_create (ENetSocketType type)
{
return socket (PF_INET, type == ENET_SOCKET_TYPE_DATAGRAM ? SOCK_DGRAM : SOCK_STREAM, 0);
}
int
enet_socket_set_option (ENetSocket socket, ENetSocketOption option, int value)
{
int result = SOCKET_ERROR;
switch (option)
{
case ENET_SOCKOPT_NONBLOCK:
{
u_long nonBlocking = (u_long) value;
result = ioctlsocket (socket, FIONBIO, & nonBlocking);
break;
}
case ENET_SOCKOPT_BROADCAST:
result = setsockopt (socket, SOL_SOCKET, SO_BROADCAST, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_REUSEADDR:
result = setsockopt (socket, SOL_SOCKET, SO_REUSEADDR, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVBUF:
result = setsockopt (socket, SOL_SOCKET, SO_RCVBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDBUF:
result = setsockopt (socket, SOL_SOCKET, SO_SNDBUF, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_RCVTIMEO:
result = setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_SNDTIMEO:
result = setsockopt (socket, SOL_SOCKET, SO_SNDTIMEO, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_NODELAY:
result = setsockopt (socket, IPPROTO_TCP, TCP_NODELAY, (char *) & value, sizeof (int));
break;
case ENET_SOCKOPT_TTL:
result = setsockopt (socket, IPPROTO_IP, IP_TTL, (char *) & value, sizeof (int));
break;
default:
break;
}
return result == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_get_option (ENetSocket socket, ENetSocketOption option, int * value)
{
int result = SOCKET_ERROR, len;
switch (option)
{
case ENET_SOCKOPT_ERROR:
len = sizeof(int);
result = getsockopt (socket, SOL_SOCKET, SO_ERROR, (char *) value, & len);
break;
case ENET_SOCKOPT_TTL:
len = sizeof(int);
result = getsockopt (socket, IPPROTO_IP, IP_TTL, (char *) value, & len);
break;
default:
break;
}
return result == SOCKET_ERROR ? -1 : 0;
}
int
enet_socket_connect (ENetSocket socket, const ENetAddress * address)
{
struct sockaddr_in sin;
int result;
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
result = connect (socket, (struct sockaddr *) & sin, sizeof (struct sockaddr_in));
if (result == SOCKET_ERROR && WSAGetLastError () != WSAEWOULDBLOCK)
return -1;
return 0;
}
ENetSocket
enet_socket_accept (ENetSocket socket, ENetAddress * address)
{
SOCKET result;
struct sockaddr_in sin;
int sinLength = sizeof (struct sockaddr_in);
result = accept (socket,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL);
if (result == INVALID_SOCKET)
return ENET_SOCKET_NULL;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return result;
}
int
enet_socket_shutdown (ENetSocket socket, ENetSocketShutdown how)
{
return shutdown (socket, (int) how) == SOCKET_ERROR ? -1 : 0;
}
void
enet_socket_destroy (ENetSocket socket)
{
if (socket != INVALID_SOCKET)
closesocket (socket);
}
int
enet_socket_send (ENetSocket socket,
const ENetAddress * address,
const ENetBuffer * buffers,
size_t bufferCount)
{
struct sockaddr_in sin;
DWORD sentLength = 0;
if (address != NULL)
{
memset (& sin, 0, sizeof (struct sockaddr_in));
sin.sin_family = AF_INET;
sin.sin_port = ENET_HOST_TO_NET_16 (address -> port);
sin.sin_addr.s_addr = address -> host;
}
if (WSASendTo (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& sentLength,
0,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? sizeof (struct sockaddr_in) : 0,
NULL,
NULL) == SOCKET_ERROR)
{
if (WSAGetLastError () == WSAEWOULDBLOCK)
return 0;
return -1;
}
return (int) sentLength;
}
int
enet_socket_receive (ENetSocket socket,
ENetAddress * address,
ENetBuffer * buffers,
size_t bufferCount)
{
INT sinLength = sizeof (struct sockaddr_in);
DWORD flags = 0,
recvLength = 0;
struct sockaddr_in sin;
if (WSARecvFrom (socket,
(LPWSABUF) buffers,
(DWORD) bufferCount,
& recvLength,
& flags,
address != NULL ? (struct sockaddr *) & sin : NULL,
address != NULL ? & sinLength : NULL,
NULL,
NULL) == SOCKET_ERROR)
{
switch (WSAGetLastError ())
{
case WSAEWOULDBLOCK:
case WSAECONNRESET:
return 0;
case WSAEINTR:
case WSAEMSGSIZE:
return -2;
default:
return -1;
}
}
if (flags & MSG_PARTIAL)
return -2;
if (address != NULL)
{
address -> host = (enet_uint32) sin.sin_addr.s_addr;
address -> port = ENET_NET_TO_HOST_16 (sin.sin_port);
}
return (int) recvLength;
}
int
enet_socketset_select (ENetSocket maxSocket, ENetSocketSet * readSet, ENetSocketSet * writeSet, enet_uint32 timeout)
{
struct timeval timeVal;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
return select (maxSocket + 1, readSet, writeSet, NULL, & timeVal);
}
int
enet_socket_wait (ENetSocket socket, enet_uint32 * condition, enet_uint32 timeout)
{
fd_set readSet, writeSet;
struct timeval timeVal;
int selectCount;
timeVal.tv_sec = timeout / 1000;
timeVal.tv_usec = (timeout % 1000) * 1000;
FD_ZERO (& readSet);
FD_ZERO (& writeSet);
if (* condition & ENET_SOCKET_WAIT_SEND)
FD_SET (socket, & writeSet);
if (* condition & ENET_SOCKET_WAIT_RECEIVE)
FD_SET (socket, & readSet);
selectCount = select (socket + 1, & readSet, & writeSet, NULL, & timeVal);
if (selectCount < 0)
return -1;
* condition = ENET_SOCKET_WAIT_NONE;
if (selectCount == 0)
return 0;
if (FD_ISSET (socket, & writeSet))
* condition |= ENET_SOCKET_WAIT_SEND;
if (FD_ISSET (socket, & readSet))
* condition |= ENET_SOCKET_WAIT_RECEIVE;
return 0;
}
#endif
Binary file not shown.
Binary file not shown.
+516
View File
@@ -0,0 +1,516 @@
/** \file
* \brief User API
* IUP - A Portable User Interface Toolkit
* Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
* http://www.tecgraf.puc-rio.br/iup mailto:iup@tecgraf.puc-rio.br
*
* See Copyright Notice at the end of this file
*/
#ifndef __IUP_H
#define __IUP_H
#include "iupkey.h"
#include "iupdef.h"
#include "iup_export.h"
#ifdef __cplusplus
extern "C" {
#endif
#define IUP_NAME "IUP - Portable User Interface"
#define IUP_DESCRIPTION "Multi-platform Toolkit for Building Graphical User Interfaces"
#define IUP_COPYRIGHT "Copyright (C) 1994-2023 Tecgraf/PUC-Rio"
#define IUP_VERSION "3.31" /* bug fixes are reported only by IupVersion functions */
#define IUP_VERSION_NUMBER 331000
#define IUP_VERSION_DATE "2023/10/13" /* does not include bug fix releases */
typedef struct Ihandle_ Ihandle;
typedef int (*Icallback)(Ihandle*);
/************************************************************************/
/* Main API */
/************************************************************************/
IUP_API int IupOpen (int *argc, char ***argv);
IUP_API void IupClose (void);
IUP_API int IupIsOpened (void);
IUPIMGLIB_API void IupImageLibOpen(void);
IUP_API int IupMainLoop (void);
IUP_API int IupLoopStep (void);
IUP_API int IupLoopStepWait (void);
IUP_API int IupMainLoopLevel (void);
IUP_API void IupFlush (void);
IUP_API void IupExitLoop (void);
IUP_API void IupPostMessage (Ihandle* ih, const char* s, int i, double d, void* p);
IUP_API int IupRecordInput(const char* filename, int mode);
IUP_API int IupPlayInput(const char* filename);
IUP_API void IupUpdate (Ihandle* ih);
IUP_API void IupUpdateChildren(Ihandle* ih);
IUP_API void IupRedraw (Ihandle* ih, int children);
IUP_API void IupRefresh (Ihandle* ih);
IUP_API void IupRefreshChildren(Ihandle* ih);
IUP_API int IupExecute(const char *filename, const char* parameters);
IUP_API int IupExecuteWait(const char *filename, const char* parameters);
IUP_API int IupHelp(const char* url);
IUP_API void IupLog(const char* type, const char* format, ...);
IUP_API char* IupLoad (const char *filename);
IUP_API char* IupLoadBuffer (const char *buffer);
IUP_API char* IupVersion (void);
IUP_API char* IupVersionDate (void);
IUP_API int IupVersionNumber (void);
IUP_API void IupVersionShow (void);
IUP_API void IupSetLanguage (const char *lng);
IUP_API char* IupGetLanguage (void);
IUP_API void IupSetLanguageString(const char* name, const char* str);
IUP_API void IupStoreLanguageString(const char* name, const char* str);
IUP_API char* IupGetLanguageString(const char* name);
IUP_API void IupSetLanguagePack(Ihandle* ih);
IUP_API void IupDestroy (Ihandle* ih);
IUP_API void IupDetach (Ihandle* child);
IUP_API Ihandle* IupAppend (Ihandle* ih, Ihandle* child);
IUP_API Ihandle* IupInsert (Ihandle* ih, Ihandle* ref_child, Ihandle* child);
IUP_API Ihandle* IupGetChild (Ihandle* ih, int pos);
IUP_API int IupGetChildPos (Ihandle* ih, Ihandle* child);
IUP_API int IupGetChildCount(Ihandle* ih);
IUP_API Ihandle* IupGetNextChild (Ihandle* ih, Ihandle* child);
IUP_API Ihandle* IupGetBrother (Ihandle* ih);
IUP_API Ihandle* IupGetParent (Ihandle* ih);
IUP_API Ihandle* IupGetDialog (Ihandle* ih);
IUP_API Ihandle* IupGetDialogChild(Ihandle* ih, const char* name);
IUP_API int IupReparent (Ihandle* ih, Ihandle* new_parent, Ihandle* ref_child);
IUP_API int IupPopup (Ihandle* ih, int x, int y);
IUP_API int IupShow (Ihandle* ih);
IUP_API int IupShowXY (Ihandle* ih, int x, int y);
IUP_API int IupHide (Ihandle* ih);
IUP_API int IupMap (Ihandle* ih);
IUP_API void IupUnmap (Ihandle* ih);
IUP_API void IupResetAttribute(Ihandle* ih, const char* name);
IUP_API int IupGetAllAttributes(Ihandle* ih, char** names, int n);
IUP_API void IupCopyAttributes(Ihandle* src_ih, Ihandle* dst_ih);
IUP_API Ihandle* IupSetAtt(const char* handle_name, Ihandle* ih, const char* name, ...);
IUP_API Ihandle* IupSetAttributes (Ihandle* ih, const char *str);
IUP_API char* IupGetAttributes (Ihandle* ih);
IUP_API void IupSetAttribute (Ihandle* ih, const char* name, const char* value);
IUP_API void IupSetStrAttribute(Ihandle* ih, const char* name, const char* value);
IUP_API void IupSetStrf (Ihandle* ih, const char* name, const char* format, ...);
IUP_API void IupSetInt (Ihandle* ih, const char* name, int value);
IUP_API void IupSetFloat (Ihandle* ih, const char* name, float value);
IUP_API void IupSetDouble (Ihandle* ih, const char* name, double value);
IUP_API void IupSetRGB (Ihandle* ih, const char* name, unsigned char r, unsigned char g, unsigned char b);
IUP_API void IupSetRGBA (Ihandle* ih, const char* name, unsigned char r, unsigned char g, unsigned char b, unsigned char a);
IUP_API char* IupGetAttribute(Ihandle* ih, const char* name);
IUP_API int IupGetInt (Ihandle* ih, const char* name);
IUP_API int IupGetInt2 (Ihandle* ih, const char* name);
IUP_API int IupGetIntInt (Ihandle* ih, const char* name, int *i1, int *i2);
IUP_API float IupGetFloat (Ihandle* ih, const char* name);
IUP_API double IupGetDouble(Ihandle* ih, const char* name);
IUP_API void IupGetRGB (Ihandle* ih, const char* name, unsigned char *r, unsigned char *g, unsigned char *b);
IUP_API void IupGetRGBA (Ihandle* ih, const char* name, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a);
IUP_API void IupSetAttributeId(Ihandle* ih, const char* name, int id, const char *value);
IUP_API void IupSetStrAttributeId(Ihandle* ih, const char* name, int id, const char *value);
IUP_API void IupSetStrfId(Ihandle* ih, const char* name, int id, const char* format, ...);
IUP_API void IupSetIntId(Ihandle* ih, const char* name, int id, int value);
IUP_API void IupSetFloatId(Ihandle* ih, const char* name, int id, float value);
IUP_API void IupSetDoubleId(Ihandle* ih, const char* name, int id, double value);
IUP_API void IupSetRGBId(Ihandle* ih, const char* name, int id, unsigned char r, unsigned char g, unsigned char b);
IUP_API char* IupGetAttributeId(Ihandle* ih, const char* name, int id);
IUP_API int IupGetIntId(Ihandle* ih, const char* name, int id);
IUP_API float IupGetFloatId(Ihandle* ih, const char* name, int id);
IUP_API double IupGetDoubleId(Ihandle* ih, const char* name, int id);
IUP_API void IupGetRGBId(Ihandle* ih, const char* name, int id, unsigned char *r, unsigned char *g, unsigned char *b);
IUP_API void IupSetAttributeId2(Ihandle* ih, const char* name, int lin, int col, const char* value);
IUP_API void IupSetStrAttributeId2(Ihandle* ih, const char* name, int lin, int col, const char* value);
IUP_API void IupSetStrfId2(Ihandle* ih, const char* name, int lin, int col, const char* format, ...);
IUP_API void IupSetIntId2(Ihandle* ih, const char* name, int lin, int col, int value);
IUP_API void IupSetFloatId2(Ihandle* ih, const char* name, int lin, int col, float value);
IUP_API void IupSetDoubleId2(Ihandle* ih, const char* name, int lin, int col, double value);
IUP_API void IupSetRGBId2(Ihandle* ih, const char* name, int lin, int col, unsigned char r, unsigned char g, unsigned char b);
IUP_API char* IupGetAttributeId2(Ihandle* ih, const char* name, int lin, int col);
IUP_API int IupGetIntId2(Ihandle* ih, const char* name, int lin, int col);
IUP_API float IupGetFloatId2(Ihandle* ih, const char* name, int lin, int col);
IUP_API double IupGetDoubleId2(Ihandle* ih, const char* name, int lin, int col);
IUP_API void IupGetRGBId2(Ihandle* ih, const char* name, int lin, int col, unsigned char *r, unsigned char *g, unsigned char *b);
IUP_API void IupSetGlobal (const char* name, const char* value);
IUP_API void IupSetStrGlobal(const char* name, const char* value);
IUP_API char* IupGetGlobal (const char* name);
IUP_API Ihandle* IupSetFocus (Ihandle* ih);
IUP_API Ihandle* IupGetFocus (void);
IUP_API Ihandle* IupPreviousField(Ihandle* ih);
IUP_API Ihandle* IupNextField (Ihandle* ih);
IUP_API Icallback IupGetCallback (Ihandle* ih, const char *name);
IUP_API Icallback IupSetCallback (Ihandle* ih, const char *name, Icallback func);
IUP_API Ihandle* IupSetCallbacks(Ihandle* ih, const char *name, Icallback func, ...);
IUP_API Icallback IupGetFunction(const char *name);
IUP_API Icallback IupSetFunction(const char *name, Icallback func);
IUP_API Ihandle* IupGetHandle (const char *name);
IUP_API Ihandle* IupSetHandle (const char *name, Ihandle* ih);
IUP_API int IupGetAllNames (char** names, int n);
IUP_API int IupGetAllDialogs(char** names, int n);
IUP_API char* IupGetName (Ihandle* ih);
IUP_API void IupSetAttributeHandle(Ihandle* ih, const char* name, Ihandle* ih_named);
IUP_API Ihandle* IupGetAttributeHandle(Ihandle* ih, const char* name);
IUP_API void IupSetAttributeHandleId(Ihandle* ih, const char* name, int id, Ihandle* ih_named);
IUP_API Ihandle* IupGetAttributeHandleId(Ihandle* ih, const char* name, int id);
IUP_API void IupSetAttributeHandleId2(Ihandle* ih, const char* name, int lin, int col, Ihandle* ih_named);
IUP_API Ihandle* IupGetAttributeHandleId2(Ihandle* ih, const char* name, int lin, int col);
IUP_API char* IupGetClassName(Ihandle* ih);
IUP_API char* IupGetClassType(Ihandle* ih);
IUP_API int IupGetAllClasses(char** names, int n);
IUP_API int IupGetClassAttributes(const char* classname, char** names, int n);
IUP_API int IupGetClassCallbacks(const char* classname, char** names, int n);
IUP_API void IupSaveClassAttributes(Ihandle* ih);
IUP_API void IupCopyClassAttributes(Ihandle* src_ih, Ihandle* dst_ih);
IUP_API void IupSetClassDefaultAttribute(const char* classname, const char *name, const char* value);
IUP_API int IupClassMatch(Ihandle* ih, const char* classname);
IUP_API Ihandle* IupCreate (const char *classname);
IUP_API Ihandle* IupCreatev(const char *classname, void* *params);
IUP_API Ihandle* IupCreatep(const char *classname, void* first, ...);
/************************************************************************/
/* Elements */
/************************************************************************/
IUP_API Ihandle* IupFill (void);
IUP_API Ihandle* IupSpace(void);
IUP_API Ihandle* IupRadio (Ihandle* child);
IUP_API Ihandle* IupVbox (Ihandle* child, ...);
IUP_API Ihandle* IupVboxv (Ihandle* *children);
IUP_API Ihandle* IupZbox (Ihandle* child, ...);
IUP_API Ihandle* IupZboxv (Ihandle* *children);
IUP_API Ihandle* IupHbox (Ihandle* child, ...);
IUP_API Ihandle* IupHboxv (Ihandle* *children);
IUP_API Ihandle* IupNormalizer (Ihandle* ih_first, ...);
IUP_API Ihandle* IupNormalizerv(Ihandle* *ih_list);
IUP_API Ihandle* IupCbox (Ihandle* child, ...);
IUP_API Ihandle* IupCboxv (Ihandle* *children);
IUP_API Ihandle* IupSbox (Ihandle* child);
IUP_API Ihandle* IupSplit (Ihandle* child1, Ihandle* child2);
IUP_API Ihandle* IupScrollBox (Ihandle* child);
IUP_API Ihandle* IupFlatScrollBox(Ihandle* child);
IUP_API Ihandle* IupGridBox (Ihandle* child, ...);
IUP_API Ihandle* IupGridBoxv (Ihandle* *children);
IUP_API Ihandle* IupMultiBox (Ihandle* child, ...);
IUP_API Ihandle* IupMultiBoxv (Ihandle **children);
IUP_API Ihandle* IupExpander(Ihandle* child);
IUP_API Ihandle* IupDetachBox (Ihandle* child);
IUP_API Ihandle* IupBackgroundBox(Ihandle* child);
IUP_API Ihandle* IupFrame (Ihandle* child);
IUP_API Ihandle* IupFlatFrame (Ihandle* child);
IUP_API Ihandle* IupImage (int width, int height, const unsigned char* pixels);
IUP_API Ihandle* IupImageRGB (int width, int height, const unsigned char* pixels);
IUP_API Ihandle* IupImageRGBA (int width, int height, const unsigned char* pixels);
IUP_API Ihandle* IupItem (const char* title, const char* action);
IUP_API Ihandle* IupSubmenu (const char* title, Ihandle* child);
IUP_API Ihandle* IupSeparator (void);
IUP_API Ihandle* IupMenu (Ihandle* child, ...);
IUP_API Ihandle* IupMenuv (Ihandle* *children);
IUP_API Ihandle* IupButton (const char* title, const char* action);
IUP_API Ihandle* IupFlatButton (const char* title);
IUP_API Ihandle* IupFlatToggle (const char* title);
IUP_API Ihandle* IupDropButton (Ihandle* dropchild);
IUP_API Ihandle* IupFlatLabel (const char* title);
IUP_API Ihandle* IupFlatSeparator(void);
IUP_API Ihandle* IupCanvas (const char* action);
IUP_API Ihandle* IupDialog (Ihandle* child);
IUP_API Ihandle* IupUser (void);
IUP_API Ihandle* IupThread (void);
IUP_API Ihandle* IupLabel (const char* title);
IUP_API Ihandle* IupList (const char* action);
IUP_API Ihandle* IupFlatList (void);
IUP_API Ihandle* IupText (const char* action);
IUP_API Ihandle* IupMultiLine (const char* action);
IUP_API Ihandle* IupToggle (const char* title, const char* action);
IUP_API Ihandle* IupTimer (void);
IUP_API Ihandle* IupClipboard (void);
IUP_API Ihandle* IupProgressBar(void);
IUP_API Ihandle* IupVal (const char *type);
IUP_API Ihandle* IupFlatVal (const char *type);
IUP_API Ihandle* IupFlatTree (void);
IUP_API Ihandle* IupTabs (Ihandle* child, ...);
IUP_API Ihandle* IupTabsv (Ihandle* *children);
IUP_API Ihandle* IupFlatTabs (Ihandle* first, ...);
IUP_API Ihandle* IupFlatTabsv (Ihandle* *children);
IUP_API Ihandle* IupTree (void);
IUP_API Ihandle* IupLink (const char* url, const char* title);
IUP_API Ihandle* IupAnimatedLabel(Ihandle* animation);
IUP_API Ihandle* IupDatePick (void);
IUP_API Ihandle* IupCalendar (void);
IUP_API Ihandle* IupColorbar (void);
IUP_API Ihandle* IupGauge (void);
IUP_API Ihandle* IupDial (const char* type);
IUP_API Ihandle* IupColorBrowser(void);
/* Old controls, use SPIN attribute of IupText */
IUP_API Ihandle* IupSpin (void);
IUP_API Ihandle* IupSpinbox (Ihandle* child);
/************************************************************************/
/* Utilities */
/************************************************************************/
/* String compare utility */
IUP_API int IupStringCompare(const char* str1, const char* str2, int casesensitive, int lexicographic);
/* IupImage utilities */
IUP_API int IupSaveImageAsText(Ihandle* ih, const char* filename, const char* format, const char* name);
IUP_API Ihandle* IupImageGetHandle(const char* name);
/* IupText and IupScintilla utilities */
IUP_API void IupTextConvertLinColToPos(Ihandle* ih, int lin, int col, int *pos);
IUP_API void IupTextConvertPosToLinCol(Ihandle* ih, int pos, int *lin, int *col);
/* IupText, IupList, IupTree, IupMatrix and IupScintilla utility */
IUP_API int IupConvertXYToPos(Ihandle* ih, int x, int y);
/* OLD names, kept for backward compatibility, will never be removed. */
IUP_API void IupStoreGlobal(const char* name, const char* value);
IUP_API void IupStoreAttribute(Ihandle* ih, const char* name, const char* value);
IUP_API void IupSetfAttribute(Ihandle* ih, const char* name, const char* format, ...);
IUP_API void IupStoreAttributeId(Ihandle* ih, const char* name, int id, const char *value);
IUP_API void IupSetfAttributeId(Ihandle* ih, const char* name, int id, const char* f, ...);
IUP_API void IupStoreAttributeId2(Ihandle* ih, const char* name, int lin, int col, const char* value);
IUP_API void IupSetfAttributeId2(Ihandle* ih, const char* name, int lin, int col, const char* format, ...);
/* IupTree and IupFlatTree utilities (work for both) */
IUP_API int IupTreeSetUserId(Ihandle* ih, int id, void* userid);
IUP_API void* IupTreeGetUserId(Ihandle* ih, int id);
IUP_API int IupTreeGetId(Ihandle* ih, void *userid);
IUP_API void IupTreeSetAttributeHandle(Ihandle* ih, const char* name, int id, Ihandle* ih_named); /* deprecated, use IupSetAttributeHandleId */
/************************************************************************/
/* Pre-defined dialogs */
/************************************************************************/
IUP_API Ihandle* IupFileDlg(void);
IUP_API Ihandle* IupMessageDlg(void);
IUP_API Ihandle* IupColorDlg(void);
IUP_API Ihandle* IupFontDlg(void);
IUP_API Ihandle* IupProgressDlg(void);
IUP_API int IupGetFile(char *arq);
IUP_API void IupMessage(const char *title, const char *msg);
IUP_API void IupMessagef(const char *title, const char *format, ...);
IUP_API void IupMessageError(Ihandle* parent, const char* message);
IUP_API int IupMessageAlarm(Ihandle* parent, const char* title, const char *message, const char *buttons);
IUP_API int IupAlarm(const char *title, const char *msg, const char *b1, const char *b2, const char *b3);
IUP_API int IupScanf(const char *format, ...);
IUP_API int IupListDialog(int type, const char *title, int size, const char** list,
int op, int max_col, int max_lin, int* marks);
IUP_API int IupGetText(const char* title, char* text, int maxsize);
IUP_API int IupGetColor(int x, int y, unsigned char* r, unsigned char* g, unsigned char* b);
typedef int (*Iparamcb)(Ihandle* dialog, int param_index, void* user_data);
IUP_API int IupGetParam(const char* title, Iparamcb action, void* user_data, const char* format,...);
IUP_API int IupGetParamv(const char* title, Iparamcb action, void* user_data, const char* format, int param_count, int param_extra, void** param_data);
IUP_API Ihandle* IupParam(const char* format);
IUP_API Ihandle* IupParamBox(Ihandle* param, ...);
IUP_API Ihandle* IupParamBoxv(Ihandle* *param_array);
IUP_API Ihandle* IupLayoutDialog(Ihandle* dialog);
IUP_API Ihandle* IupElementPropertiesDialog(Ihandle* parent, Ihandle* elem);
IUP_API Ihandle* IupGlobalsDialog(void);
IUP_API Ihandle* IupClassInfoDialog(Ihandle* parent);
#ifdef __cplusplus
}
#endif
/************************************************************************/
/* Common Flags and Return Values */
/************************************************************************/
#define IUP_ERROR 1
#define IUP_NOERROR 0
#define IUP_OPENED -1
#define IUP_INVALID -1
#define IUP_INVALID_ID -10
/************************************************************************/
/* Callback Return Values */
/************************************************************************/
#define IUP_IGNORE -1
#define IUP_DEFAULT -2
#define IUP_CLOSE -3
#define IUP_CONTINUE -4
/************************************************************************/
/* IupPopup and IupShowXY Parameter Values */
/************************************************************************/
#define IUP_CENTER 0xFFFF /* 65535 */
#define IUP_LEFT 0xFFFE /* 65534 */
#define IUP_RIGHT 0xFFFD /* 65533 */
#define IUP_MOUSEPOS 0xFFFC /* 65532 */
#define IUP_CURRENT 0xFFFB /* 65531 */
#define IUP_CENTERPARENT 0xFFFA /* 65530 */
#define IUP_LEFTPARENT 0xFFF9 /* 65529 */
#define IUP_RIGHTPARENT 0xFFF8 /* 65528 */
#define IUP_TOP IUP_LEFT
#define IUP_BOTTOM IUP_RIGHT
#define IUP_TOPPARENT IUP_LEFTPARENT
#define IUP_BOTTOMPARENT IUP_RIGHTPARENT
/************************************************************************/
/* SHOW_CB Callback Values */
/************************************************************************/
enum{IUP_SHOW, IUP_RESTORE, IUP_MINIMIZE, IUP_MAXIMIZE, IUP_HIDE};
/************************************************************************/
/* SCROLL_CB Callback Values */
/************************************************************************/
enum{IUP_SBUP, IUP_SBDN, IUP_SBPGUP, IUP_SBPGDN, IUP_SBPOSV, IUP_SBDRAGV,
IUP_SBLEFT, IUP_SBRIGHT, IUP_SBPGLEFT, IUP_SBPGRIGHT, IUP_SBPOSH, IUP_SBDRAGH};
/************************************************************************/
/* Mouse Button Values and Macros */
/************************************************************************/
#define IUP_BUTTON1 '1'
#define IUP_BUTTON2 '2'
#define IUP_BUTTON3 '3'
#define IUP_BUTTON4 '4'
#define IUP_BUTTON5 '5'
#define iup_isshift(_s) (_s[0]=='S')
#define iup_iscontrol(_s) (_s[1]=='C')
#define iup_isbutton1(_s) (_s[2]=='1')
#define iup_isbutton2(_s) (_s[3]=='2')
#define iup_isbutton3(_s) (_s[4]=='3')
#define iup_isdouble(_s) (_s[5]=='D')
#define iup_isalt(_s) (_s[6]=='A')
#define iup_issys(_s) (_s[7]=='Y')
#define iup_isbutton4(_s) (_s[8]=='4')
#define iup_isbutton5(_s) (_s[9]=='5')
/* Old definitions for backward compatibility */
#define isshift iup_isshift
#define iscontrol iup_iscontrol
#define isbutton1 iup_isbutton1
#define isbutton2 iup_isbutton2
#define isbutton3 iup_isbutton3
#define isdouble iup_isdouble
#define isalt iup_isalt
#define issys iup_issys
#define isbutton4 iup_isbutton4
#define isbutton5 iup_isbutton5
/************************************************************************/
/* Pre-Defined Masks */
/************************************************************************/
#define IUP_MASK_FLOAT "[+/-]?(/d+/.?/d*|/./d+)"
#define IUP_MASK_UFLOAT "(/d+/.?/d*|/./d+)"
#define IUP_MASK_EFLOAT "[+/-]?(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?"
#define IUP_MASK_UEFLOAT "(/d+/.?/d*|/./d+)([eE][+/-]?/d+)?"
#define IUP_MASK_FLOATCOMMA "[+/-]?(/d+/,?/d*|/,/d+)"
#define IUP_MASK_UFLOATCOMMA "(/d+/,?/d*|/,/d+)"
#define IUP_MASK_INT "[+/-]?/d+"
#define IUP_MASK_UINT "/d+"
/* Old definitions for backward compatibility */
#define IUPMASK_FLOAT IUP_MASK_FLOAT
#define IUPMASK_UFLOAT IUP_MASK_UFLOAT
#define IUPMASK_EFLOAT IUP_MASK_EFLOAT
#define IUPMASK_INT IUP_MASK_INT
#define IUPMASK_UINT IUP_MASK_UINT
/************************************************************************/
/* IupGetParam Callback situations */
/************************************************************************/
#define IUP_GETPARAM_BUTTON1 -1
#define IUP_GETPARAM_INIT -2
#define IUP_GETPARAM_BUTTON2 -3
#define IUP_GETPARAM_BUTTON3 -4
#define IUP_GETPARAM_CLOSE -5
#define IUP_GETPARAM_MAP -6
#define IUP_GETPARAM_OK IUP_GETPARAM_BUTTON1
#define IUP_GETPARAM_CANCEL IUP_GETPARAM_BUTTON2
#define IUP_GETPARAM_HELP IUP_GETPARAM_BUTTON3
/************************************************************************/
/* Used by IupColorbar */
/************************************************************************/
#define IUP_PRIMARY -1
#define IUP_SECONDARY -2
/************************************************************************/
/* Record Input Modes */
/************************************************************************/
enum {IUP_RECBINARY, IUP_RECTEXT};
/************************************************************************/
/* Replacement for the WinMain in Windows, */
/* this allows the application to start from "main". */
/* Used only for Watcom. */
/************************************************************************/
#if defined (__WATCOMC__)
#ifdef __cplusplus
extern "C" {
int IupMain (int argc, char** argv); /* In C++ we have to declare the prototype */
}
#endif
#define main IupMain /* this is the trick for Watcom and MetroWerks */
#endif
/******************************************************************************
* Copyright (C) 1994-2019 Tecgraf/PUC-Rio.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
******************************************************************************/
#endif
@@ -0,0 +1,464 @@
/** \file
* \brief Class Callback Utilities.
*/
#ifndef __IUP_CLASS_CBS_HPP
#define __IUP_CLASS_CBS_HPP
#define IUP_CLASS_GET_OBJECT(__ih, __class) dynamic_cast<__class*>((__class*)IupGetAttribute(__ih, #__class "->this"))
#define IUP_CLASS_INITCALLBACK(__ih, __class) \
IupSetAttribute(__ih, #__class "->this", (char*)this)
#define IUP_CLASS_SETCALLBACK(__ih, __name, __cb) \
IupSetCallback(__ih, __name, (Icallback)CB_##__cb)
#ifdef __IUP_PLUS_H
#define IUP_PLUS_GET_OBJECT(__elem, __class) dynamic_cast<__class*>((__class*)IupGetAttribute(__elem.GetHandle(), #__class "->this"))
#define IUP_PLUS_INITCALLBACK(__elem, __class) \
IupSetAttribute(__elem.GetHandle(), #__class "->this", (char*)this)
#define IUP_PLUS_SETCALLBACK(__elem, __name, __cb) \
IupSetCallback(__elem.GetHandle(), __name, (Icallback)CB_##__cb)
#endif
#define IUP_CLASS_DECLARECALLBACK_IFn(__class, __cb) \
int __cb(Ihandle* ih); \
static int CB_##__cb(Ihandle* ih) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih); \
}
#define IUP_CLASS_DECLARECALLBACK_IFni(__class, __cb) \
int __cb(Ihandle* ih, int i1); \
static int CB_##__cb(Ihandle* ih, int i1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2); \
static int CB_##__cb(Ihandle* ih, int i1, int i2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, i5); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiiii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, i5, i6); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiiiiC(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6, struct _cdCanvas* canvas); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6, struct _cdCanvas* canvas) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, i5, i6, canvas); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnC(__class, __cb) \
int __cb(Ihandle* ih, struct _cdCanvas* canvas); \
static int CB_##__cb(Ihandle* ih, struct _cdCanvas* canvas) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, canvas); \
}
#define IUP_CLASS_DECLARECALLBACK_dIFnii(__class, __cb) \
double __cb(Ihandle* ih, int i1, int i2); \
static double CB_##__cb(Ihandle* ih, int i1, int i2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2); \
}
#define IUP_CLASS_DECLARECALLBACK_sIFni(__class, __cb) \
char* __cb(Ihandle* ih, int i1); \
static char* CB_##__cb(Ihandle* ih, int i1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1); \
}
#define IUP_CLASS_DECLARECALLBACK_sIFnii(__class, __cb) \
char* __cb(Ihandle* ih, int i1, int i2); \
static char* CB_##__cb(Ihandle* ih, int i1, int i2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2); \
}
#define IUP_CLASS_DECLARECALLBACK_sIFniis(__class, __cb) \
char* __cb(Ihandle* ih, int i1, int i2, char* s); \
static char* CB_##__cb(Ihandle* ih, int i1, int i2, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnff(__class, __cb) \
int __cb(Ihandle* ih, float f1, float f2); \
static int CB_##__cb(Ihandle* ih, float f1, float f2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, f1, f2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniff(__class, __cb) \
int __cb(Ihandle* ih, int i1, float f1, float f2); \
static int CB_##__cb(Ihandle* ih, int i1, float f1, float f2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, f1, f2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnfiis(__class, __cb) \
int __cb(Ihandle* ih, float f1, int i1, int i2, char* s); \
static int CB_##__cb(Ihandle* ih, float f1, int i1, int i2, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, f1, i1, i2, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnd(__class, __cb) \
int __cb(Ihandle* ih, double d1); \
static int CB_##__cb(Ihandle* ih, double d1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, d1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFndds(__class, __cb) \
int __cb(Ihandle* ih, double d1, double d2, char* s); \
static int CB_##__cb(Ihandle* ih, double d1, double d2, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, d1, d2, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniid(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, double d1); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, double d1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, d1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniidd(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, double d1, double d2); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, double d1, double d2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, d1, d2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiddi(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, double d1, double d2, int i3); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, double d1, double d2, int i3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, d1, d2, i3); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniidds(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, double d1, double d2, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, double d1, double d2, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, d1, d2, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiIII(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int *I1, int *I2, int *I3); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int *I1, int *I2, int *I3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, I1, I2, I3); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniIIII(__class, __cb) \
int __cb(Ihandle* ih, int i1, int *I1, int *I2, int *I3, int *I4); \
static int CB_##__cb(Ihandle* ih, int i1, int *I1, int *I2, int *I3, int *I4) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, I1, I2, I3, I4); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnIi(__class, __cb) \
int __cb(Ihandle* ih, int *I1, int i1); \
static int CB_##__cb(Ihandle* ih, int *I1, int i1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, I1, i1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnccc(__class, __cb) \
int __cb(Ihandle* ih, char c1, char c2, char c3); \
static int CB_##__cb(Ihandle* ih, char c1, char c2, char c3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, c1, c2, c3); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnis(__class, __cb) \
int __cb(Ihandle* ih, int i1, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniis(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiis(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiis(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiiis(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, i5, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniiiiiis(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6, char* s); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, int i3, int i4, int i5, int i6, char* s) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, i3, i4, i5, i6, s); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnss(__class, __cb) \
int __cb(Ihandle* ih, char* s1, char* s2); \
static int CB_##__cb(Ihandle* ih, char* s1, char* s2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, s2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFns(__class, __cb) \
int __cb(Ihandle* ih, char* s1); \
static int CB_##__cb(Ihandle* ih, char* s1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnsi(__class, __cb) \
int __cb(Ihandle* ih, char* s1, int i1); \
static int CB_##__cb(Ihandle* ih, char* s1, int i1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, i1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnsii(__class, __cb) \
int __cb(Ihandle* ih, char* s1, int i1, int i2); \
static int CB_##__cb(Ihandle* ih, char* s1, int i1, int i2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, i1, i2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnsiii(__class, __cb) \
int __cb(Ihandle* ih, char* s1, int i1, int i2, int i3); \
static int CB_##__cb(Ihandle* ih, char* s1, int i1, int i2, int i3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, i1, i2, i3); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnnii(__class, __cb) \
int __cb(Ihandle* ih, Ihandle* ih1, int i1, int i2); \
static int CB_##__cb(Ihandle* ih, Ihandle* ih1, int i1, int i2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, ih1, i1, i2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnnn(__class, __cb) \
int __cb(Ihandle* ih, Ihandle* ih1, Ihandle *ih2); \
static int CB_##__cb(Ihandle* ih, Ihandle* ih1, Ihandle *ih2) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, ih1, ih2); \
}
#define IUP_CLASS_DECLARECALLBACK_IFniinsii(__class, __cb) \
int __cb(Ihandle* ih, int i1, int i2, Ihandle* ih1, char* s, int i3, int i4); \
static int CB_##__cb(Ihandle* ih, int i1, int i2, Ihandle* ih1, char* s, int i3, int i4) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, i1, i2, ih1, s, i3, i4); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnsVi(__class, __cb) \
int __cb(Ihandle* ih, char* s1, void* V1, int i1); \
static int CB_##__cb(Ihandle* ih, char* s1, void* V1, int i1) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, V1, i1); \
}
#define IUP_CLASS_DECLARECALLBACK_IFnsViii(__class, __cb) \
int __cb(Ihandle* ih, char* s1, void* V1, int i1, int i2, int i3); \
static int CB_##__cb(Ihandle* ih, char* s1, void* V1, int i1, int i2, int i3) \
{ \
__class* obj = IUP_CLASS_GET_OBJECT(ih, __class); \
return obj->__cb(ih, s1, V1, i1, i2, i3); \
}
/* #define IUP_CLASS_DEBUG */
#ifdef IUP_CLASS_DEBUG
class IUP_CLASS_DUMMY
{
// Used to check for errors in the definitions
IUP_CLASS_DECLARECALLBACK_IFn(IUP_CLASS_DUMMY, IFn);
IUP_CLASS_DECLARECALLBACK_IFni(IUP_CLASS_DUMMY, IFni);
IUP_CLASS_DECLARECALLBACK_IFnii(IUP_CLASS_DUMMY, IFnii);
IUP_CLASS_DECLARECALLBACK_IFniii(IUP_CLASS_DUMMY, IFniii);
IUP_CLASS_DECLARECALLBACK_IFniiii(IUP_CLASS_DUMMY, IFniiii);
IUP_CLASS_DECLARECALLBACK_IFniiiii(IUP_CLASS_DUMMY, IFniiiii);
IUP_CLASS_DECLARECALLBACK_IFniiiiii(IUP_CLASS_DUMMY, IFniiiiii);
IUP_CLASS_DECLARECALLBACK_IFniiiiiiC(IUP_CLASS_DUMMY, IFniiiiiiC);
IUP_CLASS_DECLARECALLBACK_IFnC(IUP_CLASS_DUMMY, IFnC);
IUP_CLASS_DECLARECALLBACK_dIFnii(IUP_CLASS_DUMMY, dIFnii);
IUP_CLASS_DECLARECALLBACK_sIFni(IUP_CLASS_DUMMY, sIFni);
IUP_CLASS_DECLARECALLBACK_sIFnii(IUP_CLASS_DUMMY, sIFnii);
IUP_CLASS_DECLARECALLBACK_sIFniis(IUP_CLASS_DUMMY, sIFniis);
IUP_CLASS_DECLARECALLBACK_IFnff(IUP_CLASS_DUMMY, IFnff);
IUP_CLASS_DECLARECALLBACK_IFniff(IUP_CLASS_DUMMY, IFniff);
IUP_CLASS_DECLARECALLBACK_IFnfiis(IUP_CLASS_DUMMY, IFnfiis);
IUP_CLASS_DECLARECALLBACK_IFnd(IUP_CLASS_DUMMY, IFnd);
IUP_CLASS_DECLARECALLBACK_IFndds(IUP_CLASS_DUMMY, IFndds);
IUP_CLASS_DECLARECALLBACK_IFniid(IUP_CLASS_DUMMY, IFniid);
IUP_CLASS_DECLARECALLBACK_IFniidd(IUP_CLASS_DUMMY, IFniidd);
IUP_CLASS_DECLARECALLBACK_IFniiddi(IUP_CLASS_DUMMY, IFniiddi);
IUP_CLASS_DECLARECALLBACK_IFniidds(IUP_CLASS_DUMMY, IFniidds);
IUP_CLASS_DECLARECALLBACK_IFniiIII(IUP_CLASS_DUMMY, IFniiIII);
IUP_CLASS_DECLARECALLBACK_IFniIIII(IUP_CLASS_DUMMY, IFniIIII);
IUP_CLASS_DECLARECALLBACK_IFnIi(IUP_CLASS_DUMMY, IFnIi);
IUP_CLASS_DECLARECALLBACK_IFnccc(IUP_CLASS_DUMMY, IFnccc);
IUP_CLASS_DECLARECALLBACK_IFnis(IUP_CLASS_DUMMY, IFnis);
IUP_CLASS_DECLARECALLBACK_IFniis(IUP_CLASS_DUMMY, IFniis);
IUP_CLASS_DECLARECALLBACK_IFniiis(IUP_CLASS_DUMMY, IFniiis);
IUP_CLASS_DECLARECALLBACK_IFniiiis(IUP_CLASS_DUMMY, IFniiiis);
IUP_CLASS_DECLARECALLBACK_IFniiiiis(IUP_CLASS_DUMMY, IFniiiiis);
IUP_CLASS_DECLARECALLBACK_IFniiiiiis(IUP_CLASS_DUMMY, IFniiiiiis);
IUP_CLASS_DECLARECALLBACK_IFnss(IUP_CLASS_DUMMY, IFnss);
IUP_CLASS_DECLARECALLBACK_IFns(IUP_CLASS_DUMMY, IFns);
IUP_CLASS_DECLARECALLBACK_IFnsi(IUP_CLASS_DUMMY, IFnsi);
IUP_CLASS_DECLARECALLBACK_IFnsii(IUP_CLASS_DUMMY, IFnsii);
IUP_CLASS_DECLARECALLBACK_IFnsiii(IUP_CLASS_DUMMY, IFnsiii);
IUP_CLASS_DECLARECALLBACK_IFnnii(IUP_CLASS_DUMMY, IFnnii);
IUP_CLASS_DECLARECALLBACK_IFnnn(IUP_CLASS_DUMMY, IFnnn);
IUP_CLASS_DECLARECALLBACK_IFniinsii(IUP_CLASS_DUMMY, IFniinsii);
IUP_CLASS_DECLARECALLBACK_IFnsVi(IUP_CLASS_DUMMY, IFnsVi);
IUP_CLASS_DECLARECALLBACK_IFnsViii(IUP_CLASS_DUMMY, IFnsViii);
};
class SampleClass
{
int sample_count;
public:
SampleClass()
{
sample_count = 0;
Ihandle* button1 = IupButton("Inc", NULL);
Ihandle* button2 = IupButton("Dec", NULL);
Ihandle* dialog = IupDialog(IupHbox(button1, button2, NULL));
// 1) Register "this" object as a callback receiver (need only once)
IUP_CLASS_INITCALLBACK(dialog, SampleClass);
// 2) Associate the callback with the button
IUP_CLASS_SETCALLBACK(button1, "ACTION", ButtonAction1);
IUP_CLASS_SETCALLBACK(button2, "ACTION", ButtonAction2);
IupShow(dialog);
};
protected:
// 3) Declare the callback as a member function
IUP_CLASS_DECLARECALLBACK_IFn(SampleClass, ButtonAction1);
IUP_CLASS_DECLARECALLBACK_IFn(SampleClass, ButtonAction2);
};
// 4) Define the callback as a member function
int SampleClass::ButtonAction1(Ihandle*)
{
sample_count++;
return IUP_DEFAULT;
}
int SampleClass::ButtonAction2(Ihandle*)
{
sample_count--;
return IUP_DEFAULT;
}
#endif // IUP_CLASS_DEBUG
#endif
@@ -0,0 +1,60 @@
/** \file
* \brief Configuration file Utilities
*
* See Copyright Notice in "iup.h"
*/
#ifndef IUP_CONFIG_H
#define IUP_CONFIG_H
#if defined(__cplusplus)
extern "C" {
#endif
IUP_API Ihandle* IupConfig(void);
IUP_API int IupConfigLoad(Ihandle* ih);
IUP_API int IupConfigSave(Ihandle* ih);
/****************************************************************/
IUP_API void IupConfigSetVariableStr(Ihandle* ih, const char* group, const char* key, const char* value);
IUP_API void IupConfigSetVariableStrId(Ihandle* ih, const char* group, const char* key, int id, const char* value);
IUP_API void IupConfigSetVariableInt(Ihandle* ih, const char* group, const char* key, int value);
IUP_API void IupConfigSetVariableIntId(Ihandle* ih, const char* group, const char* key, int id, int value);
IUP_API void IupConfigSetVariableDouble(Ihandle* ih, const char* group, const char* key, double value);
IUP_API void IupConfigSetVariableDoubleId(Ihandle* ih, const char* group, const char* key, int id, double value);
IUP_API const char* IupConfigGetVariableStr(Ihandle* ih, const char* group, const char* key);
IUP_API const char* IupConfigGetVariableStrId(Ihandle* ih, const char* group, const char* key, int id);
IUP_API int IupConfigGetVariableInt(Ihandle* ih, const char* group, const char* key);
IUP_API int IupConfigGetVariableIntId(Ihandle* ih, const char* group, const char* key, int id);
IUP_API double IupConfigGetVariableDouble(Ihandle* ih, const char* group, const char* key);
IUP_API double IupConfigGetVariableDoubleId(Ihandle* ih, const char* group, const char* key, int id);
IUP_API const char* IupConfigGetVariableStrDef(Ihandle* ih, const char* group, const char* key, const char* def);
IUP_API const char* IupConfigGetVariableStrIdDef(Ihandle* ih, const char* group, const char* key, int id, const char* def);
IUP_API int IupConfigGetVariableIntDef(Ihandle* ih, const char* group, const char* key, int def);
IUP_API int IupConfigGetVariableIntIdDef(Ihandle* ih, const char* group, const char* key, int id, int def);
IUP_API double IupConfigGetVariableDoubleDef(Ihandle* ih, const char* group, const char* key, double def);
IUP_API double IupConfigGetVariableDoubleIdDef(Ihandle* ih, const char* group, const char* key, int id, double def);
IUP_API void IupConfigCopy(Ihandle* ih1, Ihandle* ih2, const char* exclude_prefix);
/****************************************************************/
IUP_API void IupConfigSetListVariable(Ihandle* ih, const char *group, const char* key, const char* value, int add);
IUP_API void IupConfigRecentInit(Ihandle* ih, Ihandle* menu, Icallback recent_cb, int max_recent);
IUP_API void IupConfigRecentUpdate(Ihandle* ih, const char* filename);
IUP_API void IupConfigDialogShow(Ihandle* ih, Ihandle* dialog, const char* name);
IUP_API void IupConfigDialogClosed(Ihandle* ih, Ihandle* dialog, const char* name);
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,83 @@
#ifndef __IUP_EXPORT_H
#define __IUP_EXPORT_H
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
/** @cond DOXYGEN_SHOULD_IGNORE_THIS */
/* Mark the official functions */
#ifndef IUP_API
#ifdef IUP_BUILD_LIBRARY
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#define IUP_API EMSCRIPTEN_KEEPALIVE
#elif WIN32
#define IUP_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define IUP_API __attribute__ ((visibility("default")))
#else
#define IUP_API
#endif
#else
#define IUP_API
#endif /* IUP_BUILD_LIBRARY */
#endif /* IUP_API */
/* Mark the internal SDK functions (some not official but need to be exported) */
#ifndef IUP_SDK_API
#ifdef IUP_BUILD_LIBRARY
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#define IUP_SDK_API EMSCRIPTEN_KEEPALIVE
#elif WIN32
#define IUP_SDK_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define IUP_SDK_API __attribute__ ((visibility("default")))
#else
#define IUP_SDK_API
#endif
#else
#define IUP_SDK_API
#endif /* IUP_BUILD_LIBRARY */
#endif /* IUP_SDK_API */
/* Mark the driver functions that need to be exported */
#ifndef IUP_DRV_API
#ifdef IUP_BUILD_LIBRARY
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#define IUP_DRV_API EMSCRIPTEN_KEEPALIVE
#elif WIN32
#define IUP_DRV_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define IUP_DRV_API __attribute__ ((visibility("default")))
#else
#define IUP_DRV_API
#endif
#else
#define IUP_DRV_API
#endif /* IUP_BUILD_LIBRARY */
#endif /* IUP_DRV_API */
/* Mark the IupImageLib function, it does not have a header of its own */
#ifndef IUPIMGLIB_API
#ifdef IUPIMGLIB_BUILD_LIBRARY
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#define IUPIMGLIB_API EMSCRIPTEN_KEEPALIVE
#elif WIN32
#define IUPIMGLIB_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define IUPIMGLIB_API __attribute__ ((visibility("default")))
#else
#define IUPIMGLIB_API
#endif
#else
#define IUPIMGLIB_API
#endif /* IUPIMGLIB_BUILD_LIBRARY */
#endif /* IUPIMGLIB_API */
/** @endcond DOXYGEN_SHOULD_IGNORE_THIS */
#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
#endif /* __IUP_EXPORT_H */
@@ -0,0 +1,70 @@
/** \file
* \brief Plot component for Iup.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUP_MGLPLOT_H
#define __IUP_MGLPLOT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Initialize IupMglPlot widget class */
void IupMglPlotOpen(void);
/* Create an IupMglPlot widget instance */
Ihandle* IupMglPlot(void);
/***********************************************/
/* Additional API */
/* Linear Data Only */
void IupMglPlotBegin(Ihandle *ih, int dim);
void IupMglPlotAdd1D(Ihandle *ih, const char* name, double y);
void IupMglPlotAdd2D(Ihandle *ih, double x, double y);
void IupMglPlotAdd3D(Ihandle *ih, double x, double y, double z);
int IupMglPlotEnd(Ihandle *ih);
/* Linear (dim=1,2,3), Planar (dim=1), Volumetric (dim=1) */
int IupMglPlotNewDataSet(Ihandle *ih, int dim);
/* Linear Data Only */
void IupMglPlotInsert1D(Ihandle* ih, int ds_index, int sample_index, const char** names, const double* y, int count);
void IupMglPlotInsert2D(Ihandle* ih, int ds_index, int sample_index, const double* x, const double* y, int count);
void IupMglPlotInsert3D(Ihandle* ih, int ds_index, int sample_index, const double* x, const double* y, const double* z, int count);
/* Linear Data Only */
void IupMglPlotSet1D(Ihandle* ih, int ds_index, const char** names, const double* y, int count);
void IupMglPlotSet2D(Ihandle* ih, int ds_index, const double* x, const double* y, int count);
void IupMglPlotSet3D(Ihandle* ih, int ds_index, const double* x, const double* y, const double* z, int count);
void IupMglPlotSetFormula(Ihandle* ih, int ds_index, const char* formulaX, const char* formulaY, const char* formulaZ, int count);
/* Linear (dim=1), Planar (dim=1), Volumetric (dim=1) */
void IupMglPlotSetData(Ihandle* ih, int ds_index, const double* data, int count_x, int count_y, int count_z);
void IupMglPlotLoadData(Ihandle* ih, int ds_index, const char* filename, int count_x, int count_y, int count_z);
void IupMglPlotSetFromFormula(Ihandle* ih, int ds_index, const char* formula, int count_x, int count_y, int count_z);
/* Only inside callbacks */
void IupMglPlotTransform(Ihandle* ih, double x, double y, double z, int *ix, int *iy);
void IupMglPlotTransformTo(Ihandle* ih, int ix, int iy, double *x, double *y, double *z);
/* Only inside callbacks */
void IupMglPlotDrawMark(Ihandle* ih, double x, double y, double z);
void IupMglPlotDrawLine(Ihandle* ih, double x1, double y1, double z1, double x2, double y2, double z2);
void IupMglPlotDrawText(Ihandle* ih, const char* text, double x, double y, double z);
void IupMglPlotPaintTo(Ihandle *ih, const char* format, int w, int h, double dpi, void *data);
/***********************************************/
/* Utility label for showing TeX labels */
Ihandle* IupMglLabel(const char* title);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,70 @@
/** \file
* \brief Plot component for Iup.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUP_PLOT_H
#define __IUP_PLOT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Initialize IupPlot widget class */
void IupPlotOpen(void);
/* Create an IupPlot widget instance */
Ihandle* IupPlot(void);
/***********************************************/
/* Additional API */
void IupPlotBegin(Ihandle *ih, int strXdata);
void IupPlotAdd(Ihandle *ih, double x, double y);
void IupPlotAddStr(Ihandle *ih, const char* x, double y);
void IupPlotAddSegment(Ihandle *ih, double x, double y);
int IupPlotEnd(Ihandle *ih);
int IupPlotLoadData(Ihandle* ih, const char* filename, int strXdata);
/* available only when linking with "iupluaplot" */
int IupPlotSetFormula(Ihandle* ih, int sample_count, const char* formula, const char* init);
void IupPlotInsert(Ihandle *ih, int ds_index, int sample_index, double x, double y);
void IupPlotInsertStr(Ihandle *ih, int ds_index, int sample_index, const char* x, double y);
void IupPlotInsertSegment(Ihandle *ih, int ds_index, int sample_index, double x, double y);
void IupPlotInsertStrSamples(Ihandle* ih, int ds_index, int sample_index, const char** x, double* y, int count);
void IupPlotInsertSamples(Ihandle* ih, int ds_index, int sample_index, double *x, double *y, int count);
void IupPlotAddSamples(Ihandle* ih, int ds_index, double *x, double *y, int count);
void IupPlotAddStrSamples(Ihandle* ih, int ds_index, const char** x, double* y, int count);
void IupPlotGetSample(Ihandle* ih, int ds_index, int sample_index, double *x, double *y);
void IupPlotGetSampleStr(Ihandle* ih, int ds_index, int sample_index, const char* *x, double *y);
int IupPlotGetSampleSelection(Ihandle* ih, int ds_index, int sample_index);
double IupPlotGetSampleExtra(Ihandle* ih, int ds_index, int sample_index);
void IupPlotSetSample(Ihandle* ih, int ds_index, int sample_index, double x, double y);
void IupPlotSetSampleStr(Ihandle* ih, int ds_index, int sample_index, const char* x, double y);
void IupPlotSetSampleSelection(Ihandle* ih, int ds_index, int sample_index, int selected);
void IupPlotSetSampleExtra(Ihandle* ih, int ds_index, int sample_index, double extra);
void IupPlotTransform(Ihandle* ih, double x, double y, double *cnv_x, double *cnv_y);
void IupPlotTransformTo(Ihandle* ih, double cnv_x, double cnv_y, double *x, double *y);
int IupPlotFindSample(Ihandle* ih, double cnv_x, double cnv_y, int *ds_index, int *sample_index);
int IupPlotFindSegment(Ihandle* ih, double cnv_x, double cnv_y, int *ds_index, int *sample_index1, int *sample_index2);
struct _cdCanvas;
void IupPlotPaintTo(Ihandle *ih, struct _cdCanvas* cnv);
/***********************************************/
#ifdef __cplusplus
}
#endif
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,29 @@
/** \file
* \brief Scintilla control.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUP_SCINTILLA_H
#define __IUP_SCINTILLA_H
#ifdef __cplusplus
extern "C" {
#endif
void IupScintillaOpen(void);
Ihandle *IupScintilla(void);
Ihandle *IupScintillaDlg(void);
#ifdef SCINTILLA_H
sptr_t IupScintillaSendMessage(Ihandle* ih, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
#endif
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,52 @@
/** \file
* \brief IUP API with explicit variable argument parameters.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUP_VARG_H
#define __IUP_VARG_H
#include <stdarg.h>
#include "iup.h"
#ifdef __cplusplus
extern "C" {
#endif
IUP_API void IupLogV(const char* type, const char* format, va_list arglist);
IUP_API Ihandle* IupSetAttV(const char* handle_name, Ihandle* ih, const char* name, va_list arglist);
IUP_API void IupSetStrfV(Ihandle* ih, const char* name, const char* format, va_list arglist);
IUP_API void IupSetStrfIdV(Ihandle* ih, const char* name, int id, const char* format, va_list arglist);
IUP_API void IupSetStrfId2V(Ihandle* ih, const char* name, int lin, int col, const char* format, va_list arglist);
IUP_API Ihandle* IupSetCallbacksV(Ihandle* ih, const char *name, Icallback func, va_list arglist);
IUP_API Ihandle* IupCreateV(const char *classname, void* first, va_list arglist);
IUP_API Ihandle* IupVboxV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupZboxV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupHboxV(Ihandle* child,va_list arglist);
IUP_API Ihandle* IupNormalizerV(Ihandle* ih_first, va_list arglist);
IUP_API Ihandle* IupCboxV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupGridBoxV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupMultiBoxV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupMenuV(Ihandle* child,va_list arglist);
IUP_API Ihandle* IupTabsV(Ihandle* child, va_list arglist);
IUP_API Ihandle* IupFlatTabsV(Ihandle* child, va_list arglist);
IUP_API void IupMessageV(const char *title, const char *format, va_list arglist);
IUP_API Ihandle* IupParamBoxV(Ihandle* param, va_list arglist);
IUP_API int IupGetParamV(const char* title, Iparamcb action, void* user_data, const char* format, va_list arglist);
/* must include iupglcontrols before this file to enable this declaration */
#ifdef __IUPGLCONTROLS_H
#ifndef IUP_GLCONTROLS_API
#define IUP_GLCONTROLS_API
#endif
IUP_GLCONTROLS_API Ihandle* IupGLCanvasBoxV(Ihandle* child, va_list arglist);
#endif
#endif
@@ -0,0 +1,79 @@
/** \file
* \brief Contains all function pointer typedefs.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPCBS_H
#define __IUPCBS_H
struct _cdCanvas;
typedef int (*IFidle)(void); /* idle */
typedef void (*IFentry)(void); /* entry */
typedef void (*IFi)(int); /* globalentermodal_cb, globalleavemodal_cb, */
typedef void (*IFs)(char*); /* openurl_cb */
typedef void (*IFii)(int, int); /* globalkeypress_cb */
typedef void (*IFiis)(int, int, char*); /* globalmotion_cb, openfiles_cb */
typedef void (*IFiiiis)(int, int, int, int, char*); /* globalbutton_cb */
typedef void (*IFfiis)(float,int,int,char*); /* globalwheel_cb */
typedef void (*IFvs)(void*, char*); /* handleadd_cb, handleremove_cb, imagecreate_cb, imagedestroy_cb */
typedef int (*IFn)(Ihandle*); /* default definition, same as Icallback */
typedef int (*IFni)(Ihandle*, int); /* k_any, show_cb, toggle_action, spin_cb, branchopen_cb, branchclose_cb, executeleaf_cb, showrename_cb, rightclick_cb, extended_cb, height_cb, width_cb */
typedef int (*IFnii)(Ihandle*, int, int); /* resize_cb, caret_cb, matrix_mousemove_cb, enteritem_cb, leaveitem_cb, scrolltop_cb, dropcheck_cb, selection_cb, select_cb, switch_cb, scrolling_cb, vspan_cb, hspan_cb */
typedef int (*IFniii)(Ihandle*, int, int, int); /* trayclick_cb, edition_cb */
typedef int (*IFniiii)(Ihandle*, int, int, int, int); /* dragdrop_cb */
typedef int (*IFniiiiiiC)(Ihandle*, int, int, int, int, int, int, struct _cdCanvas*); /* draw_cb */
typedef int (*IFniiiiii)(Ihandle*, int, int, int, int, int, int); /* OLD draw_cb */
typedef int (*IFnsidv)(Ihandle*, char*, int, double, void*); /* postmessage_cb */
typedef int (*IFnff)(Ihandle*, float, float); /* canvas_action */
typedef int (*IFniff)(Ihandle*,int,float,float); /* scroll_cb */
typedef int (*IFnfiis)(Ihandle*,float,int,int,char*); /* wheel_cb */
typedef int (*IFnsVi)(Ihandle*, char*, void*, int); /* dragdata_cb */
typedef int (*IFnsViii)(Ihandle*, char*, void*, int, int, int); /* dropdata_cb */
typedef int (*IFnsiii)(Ihandle*, char*, int, int, int); /* dropfiles_cb */
typedef int (*IFnssi)(Ihandle*, char*, char*, int); /* dragfilecreatename_cb */
typedef int (*IFnnii)(Ihandle*, Ihandle*, int, int); /* drop_cb */
typedef int (*IFnn)(Ihandle*, Ihandle*); /* savemarkers_cb, restoremarkers_cb */
typedef int (*IFnnn)(Ihandle*, Ihandle*, Ihandle*); /* tabchange_cb */
typedef int (*IFnss)(Ihandle*, char *, char *); /* file_cb */
typedef int (*IFns)(Ihandle*, char *); /* multiselect_cb */
typedef int (*IFnsi)(Ihandle*, char *, int); /* copydata_cb */
typedef int (*IFnis)(Ihandle*, int, char *); /* text_action, multiline_action, edit_cb, rename_cb */
typedef int (*IFnsii)(Ihandle*, char*, int, int); /* list_action */
typedef int (*IFniis)(Ihandle*, int, int, char*); /* motion_cb, click_cb, value_edit_cb */
typedef int (*IFniiis)(Ihandle*, int, int, int, char*); /* touch_cb, dblclick_cb */
typedef int (*IFniiiis)(Ihandle*, int, int, int, int, char*); /* button_cb, matrix_action, mousemotion_cb */
typedef int (*IFniiiiiis)(Ihandle*, int, int, int, int, int, int, char*); /* mouseclick_cb */
typedef int (*IFnIi)(Ihandle*, int*, int); /* multiselection_cb, multiunselection_cb */
typedef int (*IFnd)(Ihandle*, double); /* mousemove_cb, button_press_cb, button_release_cb */
typedef int (*IFniiIII)(Ihandle*, int, int, int*, int*, int*); /* fgcolor_cb, bgcolor_cb */
typedef int (*IFniinsii)(Ihandle*, int, int, Ihandle*, char*, int, int); /* dropselect_cb */
typedef int (*IFnccc)(Ihandle*, unsigned char, unsigned char, unsigned char); /* drag_cb, change_cb */
typedef int (*IFniIIII)(Ihandle*, int, int*, int*, int*, int*); /* multitouch_cb */
typedef int (*IFnC)(Ihandle*, struct _cdCanvas*); /* postdraw_cb, predraw_cb */
typedef int (*IFniidd)(Ihandle*, int, int, double, double); /* delete_cb */
typedef int (*IFniiddi)(Ihandle*, int, int, double, double, int); /* select_cb */
typedef int (*IFniiddiddi)(Ihandle*, int, int, double, double, int, double, double, int); /* clicksegment_cb */
typedef int (*IFniidds)(Ihandle*, int, int, double, double, char*); /* plotbutton_cb */
typedef int (*IFndds)(Ihandle*, double, double, char*); /* plotmotion_cb */
typedef int (*IFnssds)(Ihandle*, char*, char*, double, char*); /* plottickformat_cb */
typedef int (*IFnni)(Ihandle*, Ihandle*, int);
typedef char* (*sIFnii)(Ihandle*, int, int); /* value_cb, font_cb */
typedef char* (*sIFni)(Ihandle*, int); /* cell_cb */
typedef char* (*sIFniis)(Ihandle*, int, int, char*); /* translatevalue_cb */
typedef double (*dIFnii)(Ihandle*, int, int); /* numericgetvalue_cb */
typedef int (*IFniid)(Ihandle*, int, int, double); /* numericsetvalue_cb */
typedef void (*IFniiv)(Ihandle*, int, int, void*); /* android_onactivityresult_cb */
#endif
@@ -0,0 +1,31 @@
/** \file
* \brief initializes dial, gauge, colorbrowser, colorbar controls.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPCONTROLS_H
#define __IUPCONTROLS_H
#ifdef __cplusplus
extern "C" {
#endif
int IupControlsOpen(void);
Ihandle* IupCells(void);
Ihandle* IupMatrix(const char *action);
Ihandle* IupMatrixList(void);
Ihandle* IupMatrixEx(void);
/* available only when linking with "iupluamatrix" */
void IupMatrixSetFormula(Ihandle* ih, int col, const char* formula, const char* init);
void IupMatrixSetDynamic(Ihandle* ih, const char* init);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,683 @@
/** \file
* \brief Callbacks, Attributes and Attribute Values definitions.
* Avoid using these definitions. Use the strings instead.
*
* See Copyright Notice in iup.h
*/
#ifndef __IUPDEF_H
#define __IUPDEF_H
/* ATTENTION: these are OLD definitions and they are NOT updated anymore since IUP 3.0 */
/* Avoid using them, directly use the strings instead. */
/* Define __IUPDEF_H to avoid the inclusion of this header */
#define IUP_RUN "RUN"
#define IUP_ENGLISH "ENGLISH"
#define IUP_PORTUGUESE "PORTUGUESE"
#define IUP_SBH "SBH"
#define IUP_SBV "SBV"
/************************************************************************/
/* Callbacks */
/************************************************************************/
#define IUP_IDLE_ACTION "IDLE_ACTION"
#define IUP_ACTION "ACTION"
#define IUP_GETFOCUS_CB "GETFOCUS_CB"
#define IUP_KILLFOCUS_CB "KILLFOCUS_CB"
#define IUP_K_ANY "K_ANY"
#define IUP_KEYPRESS_CB "KEYPRESS_CB"
#define IUP_HELP_CB "HELP_CB"
#define IUP_SCROLL_CB "SCROLL_CB"
#define IUP_RESIZE_CB "RESIZE_CB"
#define IUP_MOTION_CB "MOTION_CB"
#define IUP_BUTTON_CB "BUTTON_CB"
#define IUP_ENTERWINDOW_CB "ENTERWINDOW_CB"
#define IUP_LEAVEWINDOW_CB "LEAVEWINDOW_CB"
#define IUP_WHEEL_CB "WHEEL_CB"
#define IUP_MASK_CB "MASK_CB"
#define IUP_OPEN_CB "OPEN_CB"
#define IUP_HIGHLIGHT_CB "HIGHLIGHT_CB"
#define IUP_MENUCLOSE_CB "MENUCLOSE_CB"
#define IUP_MAP_CB "MAP_CB"
#define IUP_CLOSE_CB "CLOSE_CB"
#define IUP_SHOW_CB "SHOW_CB"
#define IUP_DROPFILES_CB "DROPFILES_CB"
#define IUP_WOM_CB "WOM_CB"
/************************************************************************/
/* Attributes */
/************************************************************************/
#define IUP_DIRECTION "DIRECTION"
#define IUP_ACTIVE "ACTIVE"
#define IUP_BGCOLOR "BGCOLOR"
#define IUP_FRAMECOLOR "FRAMECOLOR"
#define IUP_FGCOLOR "FGCOLOR"
#define IUP_COLOR "COLOR"
#define IUP_WID "WID"
#define IUP_SIZE "SIZE"
#define IUP_RASTERSIZE "RASTERSIZE"
#define IUP_TITLE "TITLE"
#define IUP_VALUE "VALUE"
#define IUP_VISIBLE "VISIBLE"
#define IUP_FONT "FONT"
#define IUP_TIP "TIP"
#define IUP_EXPAND "EXPAND"
#define IUP_SEPARATOR "SEPARATOR"
#define IUP_HOTSPOT "HOTSPOT"
#define IUP_HEIGHT "HEIGHT"
#define IUP_WIDTH "WIDTH"
#define IUP_KEY "KEY"
#define IUP_MULTIPLE "MULTIPLE"
#define IUP_DROPDOWN "DROPDOWN"
#define IUP_VISIBLE_ITEMS "VISIBLE_ITEMS"
#define IUP_MARGIN "MARGIN"
#define IUP_GAP "GAP"
#define IUP_ALIGNMENT "ALIGNMENT"
#define IUP_IMAGE "IMAGE"
#define IUP_IMINACTIVE "IMINACTIVE"
#define IUP_IMPRESS "IMPRESS"
#define IUP_WIN_SAVEBITS "WIN_SAVEBITS"
#define IUP_NC "NC"
#define IUP_MASK "MASK"
#define IUP_APPEND "APPEND"
#define IUP_BORDER "BORDER"
#define IUP_CARET "CARET"
#define IUP_SELECTION "SELECTION"
#define IUP_SELECTEDTEXT "SELECTEDTEXT"
#define IUP_INSERT "INSERT"
#define IUP_CONID "CONID"
#define IUP_CURSOR "CURSOR"
#define IUP_ICON "ICON"
#define IUP_MENUBOX "MENUBOX"
#define IUP_MINBOX "MINBOX"
#define IUP_MAXBOX "MAXBOX"
#define IUP_RESIZE "RESIZE"
#define IUP_MENU "MENU"
#define IUP_STARTFOCUS "STARTFOCUS"
#define IUP_PARENTDIALOG "PARENTDIALOG"
#define IUP_SHRINK "SHRINK"
#define IUP_DEFAULTENTER "DEFAULTENTER"
#define IUP_DEFAULTESC "DEFAULTESC"
#define IUP_X "X"
#define IUP_Y "Y"
#define IUP_TOOLBOX "TOOLBOX"
#define IUP_CONTROL "CONTROL"
#define IUP_READONLY "READONLY"
#define IUP_SCROLLBAR "SCROLLBAR"
#define IUP_POSY "POSY"
#define IUP_POSX "POSX"
#define IUP_DX "DX"
#define IUP_DY "DY"
#define IUP_XMAX "XMAX"
#define IUP_XMIN "XMIN"
#define IUP_YMAX "YMAX"
#define IUP_YMIN "YMIN"
#define IUP_RED "255 0 0"
#define IUP_GREEN "0 255 0"
#define IUP_BLUE "0 0 255"
#define IUP_MIN "MIN"
#define IUP_MAX "MAX"
#define IUP_TIME "TIME"
#define IUP_DRAG "DRAG"
#define IUP_DROP "DROP"
#define IUP_REPAINT "REPAINT"
#define IUP_TOPMOST "TOPMOST"
#define IUP_CLIPCHILDREN "CLIPCHILDREN"
#define IUP_DIALOGTYPE "DIALOGTYPE"
#define IUP_FILE "FILE"
#define IUP_MULTIPLEFILES "MULTIPLEFILES"
#define IUP_FILTER "FILTER"
#define IUP_FILTERUSED "FILTERUSED"
#define IUP_FILTERINFO "FILTERINFO"
#define IUP_EXTFILTER "EXTFILTER"
#define IUP_DIRECTORY "DIRECTORY"
#define IUP_ALLOWNEW "ALLOWNEW"
#define IUP_NOOVERWRITEPROMPT "NOOVERWRITEPROMPT"
#define IUP_NOCHANGEDIR "NOCHANGEDIR"
#define IUP_FILEEXIST "FILEEXIST"
#define IUP_STATUS "STATUS"
#define IUP_LOCKLOOP "LOCKLOOP"
#define IUP_SYSTEM "SYSTEM"
#define IUP_DRIVER "DRIVER"
#define IUP_SCREENSIZE "SCREENSIZE"
#define IUP_SYSTEMLANGUAGE "SYSTEMLANGUAGE"
#define IUP_COMPUTERNAME "COMPUTERNAME"
#define IUP_USERNAME "USERNAME"
#define IUP_OPEN "OPEN"
#define IUP_SAVE "SAVE"
#define IUP_DIR "DIR"
#define IUP_HORIZONTAL "HORIZONTAL"
#define IUP_VERTICAL "VERTICAL"
/************************************************************************/
/* Attribute Values */
/************************************************************************/
#define IUP_YES "YES"
#define IUP_NO "NO"
#define IUP_ON "ON"
#define IUP_OFF "OFF"
#define IUP_ACENTER "ACENTER"
#define IUP_ALEFT "ALEFT"
#define IUP_ARIGHT "ARIGHT"
#define IUP_ATOP "ATOP"
#define IUP_ABOTTOM "ABOTTOM"
#define IUP_NORTH "NORTH"
#define IUP_SOUTH "SOUTH"
#define IUP_WEST "WEST"
#define IUP_EAST "EAST"
#define IUP_NE "NE"
#define IUP_SE "SE"
#define IUP_NW "NW"
#define IUP_SW "SW"
#define IUP_FULLSCREEN "FULLSCREEN"
#define IUP_FULL "FULL"
#define IUP_HALF "HALF"
#define IUP_THIRD "THIRD"
#define IUP_QUARTER "QUARTER"
#define IUP_EIGHTH "EIGHTH"
#define IUP_ARROW "ARROW"
#define IUP_BUSY "BUSY"
#define IUP_RESIZE_N "RESIZE_N"
#define IUP_RESIZE_S "RESIZE_S"
#define IUP_RESIZE_E "RESIZE_E"
#define IUP_RESIZE_W "RESIZE_W"
#define IUP_RESIZE_NE "RESIZE_NE"
#define IUP_RESIZE_NW "RESIZE_NW"
#define IUP_RESIZE_SE "RESIZE_SE"
#define IUP_RESIZE_SW "RESIZE_SW"
#define IUP_MOVE "MOVE"
#define IUP_HAND "HAND"
#define IUP_NONE "NONE"
#define IUP_IUP "IUP"
#define IUP_CROSS "CROSS"
#define IUP_PEN "PEN"
#define IUP_TEXT "TEXT"
#define IUP_RESIZE_C "RESIZE_C"
#define IUP_OPENHAND "OPENHAND"
/************************************************************************/
/* Keys */
/************************************************************************/
#define IUP_K_exclam "K_exclam"
#define IUP_K_quotedbl "K_quotedbl"
#define IUP_K_numbersign "K_numbersign"
#define IUP_K_dollar "K_dollar"
#define IUP_K_percent "K_percent"
#define IUP_K_ampersand "K_ampersand"
#define IUP_K_quoteright "K_quoteright"
#define IUP_K_parentleft "K_parentleft"
#define IUP_K_parentright "K_parentright"
#define IUP_K_asterisk "K_asterisk"
#define IUP_K_plus "K_plus"
#define IUP_K_comma "K_comma"
#define IUP_K_minus "K_minus"
#define IUP_K_period "K_period"
#define IUP_K_slash "K_slash"
#define IUP_K_0 "K_0"
#define IUP_K_1 "K_1"
#define IUP_K_2 "K_2"
#define IUP_K_3 "K_3"
#define IUP_K_4 "K_4"
#define IUP_K_5 "K_5"
#define IUP_K_6 "K_6"
#define IUP_K_7 "K_7"
#define IUP_K_8 "K_8"
#define IUP_K_9 "K_9"
#define IUP_K_colon "K_colon"
#define IUP_K_semicolon "K_semicolon "
#define IUP_K_less "K_less"
#define IUP_K_equal "K_equal"
#define IUP_K_greater "K_greater"
#define IUP_K_question "K_question"
#define IUP_K_at "K_at"
#define IUP_K_A "K_A"
#define IUP_K_B "K_B"
#define IUP_K_C "K_C"
#define IUP_K_D "K_D"
#define IUP_K_E "K_E"
#define IUP_K_F "K_F"
#define IUP_K_G "K_G"
#define IUP_K_H "K_H"
#define IUP_K_I "K_I"
#define IUP_K_J "K_J"
#define IUP_K_K "K_K"
#define IUP_K_L "K_L"
#define IUP_K_M "K_M"
#define IUP_K_N "K_N"
#define IUP_K_O "K_O"
#define IUP_K_P "K_P"
#define IUP_K_Q "K_Q"
#define IUP_K_R "K_R"
#define IUP_K_S "K_S"
#define IUP_K_T "K_T"
#define IUP_K_U "K_U"
#define IUP_K_V "K_V"
#define IUP_K_W "K_W"
#define IUP_K_X "K_X"
#define IUP_K_Y "K_Y"
#define IUP_K_Z "K_Z"
#define IUP_K_bracketleft "K_bracketleft"
#define IUP_K_backslash "K_backslash"
#define IUP_K_bracketright "K_bracketright"
#define IUP_K_circum "K_circum"
#define IUP_K_underscore "K_underscore"
#define IUP_K_quoteleft "K_quoteleft"
#define IUP_K_a "K_a"
#define IUP_K_b "K_b"
#define IUP_K_c "K_c"
#define IUP_K_d "K_d"
#define IUP_K_e "K_e"
#define IUP_K_f "K_f"
#define IUP_K_g "K_g"
#define IUP_K_h "K_h"
#define IUP_K_i "K_i"
#define IUP_K_j "K_j"
#define IUP_K_k "K_k"
#define IUP_K_l "K_l"
#define IUP_K_m "K_m"
#define IUP_K_n "K_n"
#define IUP_K_o "K_o"
#define IUP_K_p "K_p"
#define IUP_K_q "K_q"
#define IUP_K_r "K_r"
#define IUP_K_s "K_s"
#define IUP_K_t "K_t"
#define IUP_K_u "K_u"
#define IUP_K_v "K_v"
#define IUP_K_w "K_w"
#define IUP_K_x "K_x"
#define IUP_K_y "K_y"
#define IUP_K_z "K_z"
#define IUP_K_braceleft "K_braceleft"
#define IUP_K_bar "K_bar"
#define IUP_K_braceright "K_braceright"
#define IUP_K_tilde "K_tilde"
#define IUP_K_cA "K_cA"
#define IUP_K_cB "K_cB"
#define IUP_K_cC "K_cC"
#define IUP_K_cD "K_cD"
#define IUP_K_cE "K_cE"
#define IUP_K_cF "K_cF"
#define IUP_K_cG "K_cG"
#define IUP_K_cJ "K_cJ"
#define IUP_K_cK "K_cK"
#define IUP_K_cL "K_cL"
#define IUP_K_cN "K_cN"
#define IUP_K_cO "K_cO"
#define IUP_K_cP "K_cP"
#define IUP_K_cQ "K_cQ"
#define IUP_K_cR "K_cR"
#define IUP_K_cS "K_cS"
#define IUP_K_cT "K_cT"
#define IUP_K_cU "K_cU"
#define IUP_K_cV "K_cV"
#define IUP_K_cW "K_cW"
#define IUP_K_cX "K_cX"
#define IUP_K_cY "K_cY"
#define IUP_K_cZ "K_cZ"
#define IUP_K_mA "K_mA"
#define IUP_K_mB "K_mB"
#define IUP_K_mC "K_mC"
#define IUP_K_mD "K_mD"
#define IUP_K_mE "K_mE"
#define IUP_K_mF "K_mF"
#define IUP_K_mG "K_mG"
#define IUP_K_mH "K_mH"
#define IUP_K_mI "K_mI"
#define IUP_K_mJ "K_mJ"
#define IUP_K_mK "K_mK"
#define IUP_K_mL "K_mL"
#define IUP_K_mM "K_mM"
#define IUP_K_mN "K_mN"
#define IUP_K_mO "K_mO"
#define IUP_K_mP "K_mP"
#define IUP_K_mQ "K_mQ"
#define IUP_K_mR "K_mR"
#define IUP_K_mS "K_mS"
#define IUP_K_mT "K_mT"
#define IUP_K_mU "K_mU"
#define IUP_K_mV "K_mV"
#define IUP_K_mW "K_mW"
#define IUP_K_mX "K_mX"
#define IUP_K_mY "K_mY"
#define IUP_K_mZ "K_mZ"
#define IUP_K_BS "K_BS"
#define IUP_K_TAB "K_TAB"
#define IUP_K_CR "K_CR"
#define IUP_K_SP "K_SP"
#define IUP_K_ESC "K_ESC"
#define IUP_K_sCR "K_sCR"
#define IUP_K_sTAB "K_sTAB"
#define IUP_K_cTAB "K_cTAB"
#define IUP_K_mTAB "K_mTAB"
#define IUP_K_HOME "K_HOME"
#define IUP_K_UP "K_UP"
#define IUP_K_PGUP "K_PGUP"
#define IUP_K_LEFT "K_LEFT"
#define IUP_K_RIGHT "K_RIGHT"
#define IUP_K_END "K_END"
#define IUP_K_DOWN "K_DOWN"
#define IUP_K_PGDN "K_PGDN"
#define IUP_K_MIDDLE "K_MIDDLE"
#define IUP_K_INS "K_INS"
#define IUP_K_DEL "K_DEL"
#define IUP_K_sHOME "K_sHOME"
#define IUP_K_sUP "K_sUP"
#define IUP_K_sPGUP "K_sPGUP"
#define IUP_K_sLEFT "K_sLEFT"
#define IUP_K_sRIGHT "K_sRIGHT"
#define IUP_K_sEND "K_sEND"
#define IUP_K_sDOWN "K_sDOWN"
#define IUP_K_sPGDN "K_sPGDN"
#define IUP_K_cHOME "K_cHOME"
#define IUP_K_cPGUP "K_cPGUP"
#define IUP_K_cLEFT "K_cLEFT"
#define IUP_K_cRIGHT "K_cRIGHT"
#define IUP_K_cEND "K_cEND"
#define IUP_K_cPGDN "K_cPGDN"
#define IUP_K_cUP "K_cUP"
#define IUP_K_cDOWN "K_cDOWN"
#define IUP_K_cMIDDLE "K_cMIDDLE"
#define IUP_K_cINS "K_cINS"
#define IUP_K_cDEL "K_cDEL"
#define IUP_K_mHOME "K_mHOME"
#define IUP_K_mPGUP "K_mPGUP"
#define IUP_K_mLEFT "K_mLEFT"
#define IUP_K_mRIGHT "K_mRIGHT"
#define IUP_K_mEND "K_mEND"
#define IUP_K_mPGDN "K_mPGDN"
#define IUP_K_mUP "K_mUP"
#define IUP_K_mDOWN "K_mDOWN"
#define IUP_K_mINS "K_mINS"
#define IUP_K_mDEL "K_mDEL"
#define IUP_K_F1 "K_F1"
#define IUP_K_F2 "K_F2"
#define IUP_K_F3 "K_F3"
#define IUP_K_F4 "K_F4"
#define IUP_K_F5 "K_F5"
#define IUP_K_F6 "K_F6"
#define IUP_K_F7 "K_F7"
#define IUP_K_F8 "K_F8"
#define IUP_K_F9 "K_F9"
#define IUP_K_F10 "K_F10"
#define IUP_K_F11 "K_F11"
#define IUP_K_F12 "K_F12"
#define IUP_K_sF1 "K_sF1"
#define IUP_K_sF2 "K_sF2"
#define IUP_K_sF3 "K_sF3"
#define IUP_K_sF4 "K_sF4"
#define IUP_K_sF5 "K_sF5"
#define IUP_K_sF6 "K_sF6"
#define IUP_K_sF7 "K_sF7"
#define IUP_K_sF8 "K_sF8"
#define IUP_K_sF9 "K_sF9"
#define IUP_K_sF10 "K_sF10"
#define IUP_K_sF11 "K_sF11"
#define IUP_K_sF12 "K_sF12"
#define IUP_K_cF1 "K_cF1"
#define IUP_K_cF2 "K_cF2"
#define IUP_K_cF3 "K_cF3"
#define IUP_K_cF4 "K_cF4"
#define IUP_K_cF5 "K_cF5"
#define IUP_K_cF6 "K_cF6"
#define IUP_K_cF7 "K_cF7"
#define IUP_K_cF8 "K_cF8"
#define IUP_K_cF9 "K_cF9"
#define IUP_K_cF10 "K_cF10"
#define IUP_K_cF11 "K_cF11"
#define IUP_K_cF12 "K_cF12"
#define IUP_K_mF1 "K_mF1"
#define IUP_K_mF2 "K_mF2"
#define IUP_K_mF3 "K_mF3"
#define IUP_K_mF4 "K_mF4"
#define IUP_K_mF5 "K_mF5"
#define IUP_K_mF6 "K_mF6"
#define IUP_K_mF7 "K_mF7"
#define IUP_K_mF8 "K_mF8"
#define IUP_K_mF9 "K_mF9"
#define IUP_K_mF10 "K_mF10"
#define IUP_K_m1 "K_m1"
#define IUP_K_m2 "K_m2"
#define IUP_K_m3 "K_m3"
#define IUP_K_m4 "K_m4"
#define IUP_K_m5 "K_m5"
#define IUP_K_m6 "K_m6"
#define IUP_K_m7 "K_m7"
#define IUP_K_m8 "K_m8"
#define IUP_K_m9 "K_m9"
#define IUP_K_m0 "K_m0"
/************/
/* Colorbar */
/************/
#define IUP_NUM_PARTS "NUM_PARTS"
#define IUP_NUM_CELLS "NUM_CELLS"
#define IUP_CELL "CELL"
#define IUP_PREVIEW_SIZE "PREVIEW_SIZE"
#define IUP_SHOW_PREVIEW "SHOW_PREVIEW"
#define IUP_SHOW_SECONDARY "SHOW_SECONDARY"
#define IUP_PRIMARY_CELL "PRIMARY_CELL"
#define IUP_SECONDARY_CELL "SECONDARY_CELL"
#define IUP_ORIENTATION "ORIENTATION"
#define IUP_SQUARED "SQUARED"
#define IUP_SHADOWED "SHADOWED"
#define IUP_BUFFERIZE "BUFFERIZE"
#define IUP_TRANSPARENCY "TRANSPARENCY"
#define IUP_CELL_CB "CELL_CB"
#define IUP_EXTENDED_CB "EXTENDED_CB"
#define IUP_SELECT_CB "SELECT_CB"
#define IUP_SWITCH_CB "SWITCH_CB"
#define IUP_VERTICAL "VERTICAL"
#define IUP_HORIZONTAL "HORIZONTAL"
/************/
/* Cells */
/************/
#define IUP_ALL "ALL"
#define IUP_BOXED "BOXED"
#define IUP_CLIPPED "CLIPPED"
#define IUP_TRANSPARENT "TRANSPARENT"
#define IUP_NON_SCROLLABLE_LINES "NON_SCROLLABLE_LINES"
#define IUP_NON_SCROLLABLE_COLS "NON_SCROLLABLE_COLS"
#define IUP_ORIGIN "ORIGIN"
#define IUP_NO_COLOR "NO_COLOR"
#define IUP_FIRST_LINE "FIRST_LINE"
#define IUP_FIRST_COL "FIRST_COL"
#define IUP_DOUBLE_BUFFER "DOUBLE_BUFFER"
#define IUP_LIMITS "LIMITS"
#define IUP_CANVAS "CANVAS"
#define IUP_IMAGE_CANVAS "IMAGE_CANVAS"
#define IUP_FULL_VISIBLE "FULL_VISIBLE"
#define IUP_MOUSECLICK_CB "MOUSECLICK_CB"
#define IUP_MOUSEMOTION_CB "MOUSEMOTION_CB"
#define IUP_DRAW_CB "DRAW_CB"
#define IUP_WIDTH_CB "WIDTH_CB"
#define IUP_HEIGHT_CB "HEIGHT_CB"
#define IUP_NLINES_CB "NLINES_CB"
#define IUP_NCOLS_CB "NCOLS_CB"
#define IUP_HSPAN_CB "HSPAN_CB"
#define IUP_VSPAN_CB "VSPAN_CB"
#define IUP_SCROLLING_CB "SCROLLING_CB"
/*****************/
/* ColorBrowser */
/*****************/
#define IUP_RGB "RGB"
#define IUP_CHANGE_CB "CHANGE_CB"
#define IUP_DRAG_CB "DRAG_CB"
/*****************/
/* Val */
/*****************/
#define ICTL_MOUSEMOVE_CB "MOUSEMOVE_CB"
#define ICTL_BUTTON_PRESS_CB "BUTTON_PRESS_CB"
#define ICTL_BUTTON_RELEASE_CB "BUTTON_RELEASE_CB"
#define ICTL_HORIZONTAL "HORIZONTAL"
#define ICTL_VERTICAL "VERTICAL"
#define ICTL_SHOWTICKS "SHOWTICKS"
/*****************/
/* Tabs */
/*****************/
#define ICTL_TOP "TOP"
#define ICTL_BOTTOM "BOTTOM"
#define ICTL_LEFT "LEFT"
#define ICTL_RIGHT "RIGHT"
#define ICTL_TABTYPE "TABTYPE"
#define ICTL_TABTITLE "TABTITLE"
#define ICTL_TABSIZE "TABSIZE"
#define ICTL_TABCHANGE_CB "TABCHANGE_CB"
#define ICTL_FONT "FONT"
#define ICTL_FONT_ACTIVE "FONT_ACTIVE"
#define ICTL_FONT_INACTIVE "FONT_INACTIVE"
/*****************/
/* Gauge */
/*****************/
#define ICTL_SHOW_TEXT "SHOW_TEXT"
#define ICTL_DASHED "DASHED"
#define ICTL_MARGIN "MARGIN"
#define ICTL_TEXT "TEXT"
/*****************/
/* Dial */
/*****************/
#define ICTL_DENSITY "DENSITY"
#define ICTL_HORIZONTAL "HORIZONTAL"
#define ICTL_VERTICAL "VERTICAL"
#define ICTL_CIRCULAR "CIRCULAR"
#define ICTL_UNIT "UNIT"
/*****************/
/* Matrix */
/*****************/
#define IUP_ENTERITEM_CB "ENTERITEM_CB"
#define IUP_LEAVEITEM_CB "LEAVEITEM_CB"
#define IUP_EDITION_CB "EDITION_CB"
#define IUP_CLICK_CB "CLICK_CB"
#define IUP_DROP_CB "DROP_CB"
#define IUP_DROPSELECT_CB "DROPSELECT_CB"
#define IUP_DROPCHECK_CB "DROPCHECK_CB"
#define IUP_SCROLL_CB "SCROLL_CB"
#define IUP_VALUE_CB "VALUE_CB"
#define IUP_VALUE_EDIT_CB "VALUE_EDIT_CB"
#define IUP_FIELD_CB "FIELD_CB"
#define IUP_RESIZEMATRIX "RESIZEMATRIX"
#define IUP_ADDLIN "ADDLIN"
#define IUP_ADDCOL "ADDCOL"
#define IUP_DELLIN "DELLIN"
#define IUP_DELCOL "DELCOL"
#define IUP_NUMLIN "NUMLIN"
#define IUP_NUMCOL "NUMCOL"
#define IUP_NUMLIN_VISIBLE "NUMLIN_VISIBLE"
#define IUP_NUMCOL_VISIBLE "NUMCOL_VISIBLE"
#define IUP_MARKED "MARKED"
#define IUP_WIDTHDEF "WIDTHDEF"
#define IUP_HEIGHTDEF "HEIGHTDEF"
#define IUP_AREA "AREA"
#define IUP_MARK_MODE "MARK_MODE"
#define IUP_LIN "LIN"
#define IUP_COL "COL"
#define IUP_LINCOL "LINCOL"
#define IUP_CELL "CELL"
#define IUP_EDIT_MODE "EDIT_MODE"
#define IUP_FOCUS_CELL "FOCUS_CELL"
#define IUP_ORIGIN "ORIGIN"
#define IUP_REDRAW "REDRAW"
#define IUP_PREVIOUSVALUE "PREVIOUSVALUE"
#define IUP_MOUSEMOVE_CB "MOUSEMOVE_CB"
/*****************/
/* Tree */
/*****************/
#define IUP_ADDLEAF "ADDLEAF"
#define IUP_ADDBRANCH "ADDBRANCH"
#define IUP_DELNODE "DELNODE"
#define IUP_IMAGELEAF "IMAGELEAF"
#define IUP_IMAGEBRANCHCOLLAPSED "IMAGEBRANCHCOLLAPSED"
#define IUP_IMAGEBRANCHEXPANDED "IMAGEBRANCHEXPANDED"
#define IUP_IMAGEEXPANDED "IMAGEEXPANDED"
#define IUP_KIND "KIND"
#define IUP_PARENT "PARENT"
#define IUP_DEPTH "DEPTH"
#define IUP_MARKED "MARKED"
#define IUP_ADDEXPANDED "ADDEXPANDED"
#define IUP_CTRL "CTRL"
#define IUP_SHIFT "SHIFT"
#define IUP_STATE "STATE"
#define IUP_STARTING "STARTING"
#define IUP_LEAF "LEAF"
#define IUP_BRANCH "BRANCH"
#define IUP_SELECTED "SELECTED"
#define IUP_CHILDREN "CHILDREN"
#define IUP_MARKED "MARKED"
#define IUP_ROOT "ROOT"
#define IUP_LAST "LAST"
#define IUP_PGUP "PGUP"
#define IUP_PGDN "PGDN"
#define IUP_NEXT "NEXT"
#define IUP_PREVIOUS "PREVIOUS"
#define IUP_INVERT "INVERT"
#define IUP_BLOCK "BLOCK"
#define IUP_CLEARALL "CLEARALL"
#define IUP_MARKALL "MARKALL"
#define IUP_INVERTALL "INVERTALL"
#define IUP_REDRAW "REDRAW"
#define IUP_COLLAPSED "COLLAPSED"
#define IUP_EXPANDED "EXPANDED"
#define IUP_SELECTION_CB "SELECTION_CB"
#define IUP_BRANCHOPEN_CB "BRANCHOPEN_CB"
#define IUP_BRANCHCLOSE_CB "BRANCHCLOSE_CB"
#define IUP_RIGHTCLICK_CB "RIGHTCLICK_CB"
#define IUP_EXECUTELEAF_CB "EXECUTELEAF_CB"
#define IUP_RENAMENODE_CB "RENAMENODE_CB"
#define IUP_IMGLEAF "IMGLEAF"
#define IUP_IMGCOLLAPSED "IMGCOLLAPSED"
#define IUP_IMGEXPANDED "IMGEXPANDED"
#define IUP_IMGBLANK "IMGBLANK"
#define IUP_IMGPAPER "IMGPAPER"
#endif
@@ -0,0 +1,47 @@
/** \file
* \brief Canvas Draw API
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPDRAW_H
#define __IUPDRAW_H
#ifdef __cplusplus
extern "C" {
#endif
/* all functions can be used only in IUP canvas and inside the ACTION callback */
IUP_API void IupDrawBegin(Ihandle* ih);
IUP_API void IupDrawEnd(Ihandle* ih);
/* all functions can be called only between calls to Begin and End */
IUP_API void IupDrawSetClipRect(Ihandle* ih, int x1, int y1, int x2, int y2);
IUP_API void IupDrawGetClipRect(Ihandle* ih, int *x1, int *y1, int *x2, int *y2);
IUP_API void IupDrawResetClip(Ihandle* ih);
/* color controlled by the attribute DRAWCOLOR */
/* line style or fill controlled by the attribute DRAWSTYLE */
IUP_API void IupDrawParentBackground(Ihandle* ih);
IUP_API void IupDrawLine(Ihandle* ih, int x1, int y1, int x2, int y2);
IUP_API void IupDrawRectangle(Ihandle* ih, int x1, int y1, int x2, int y2);
IUP_API void IupDrawArc(Ihandle* ih, int x1, int y1, int x2, int y2, double a1, double a2);
IUP_API void IupDrawPolygon(Ihandle* ih, int* points, int count);
IUP_API void IupDrawText(Ihandle* ih, const char* text, int len, int x, int y, int w, int h);
IUP_API void IupDrawImage(Ihandle* ih, const char* name, int x, int y, int w, int h);
IUP_API void IupDrawSelectRect(Ihandle* ih, int x1, int y1, int x2, int y2);
IUP_API void IupDrawFocusRect(Ihandle* ih, int x1, int y1, int x2, int y2);
IUP_API void IupDrawGetSize(Ihandle* ih, int *w, int *h);
IUP_API void IupDrawGetTextSize(Ihandle* ih, const char* text, int len, int *w, int *h);
IUP_API void IupDrawGetImageInfo(const char* name, int *w, int *h, int *bpp);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,21 @@
/** \file
* \brief IupDraw CD driver
*
* See Copyright Notice in iup.h
*/
#ifndef __CD_IUPDRAW_H
#define __CD_IUPDRAW_H
#ifdef __cplusplus
extern "C" {
#endif
cdContext* cdContextIupDraw(void);
#define CD_IUPDRAW cdContextIupDraw()
#ifdef __cplusplus
}
#endif
#endif /* ifndef __CD_IUPDRAW_ */
@@ -0,0 +1,24 @@
/** \file
* \brief New FileDlg (Windows Only).
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPFILEDLG_H
#define __IUPFILEDLG_H
#ifdef __cplusplus
extern "C" {
#endif
/* the only exported function,
once called it will replace regular IupFileDlg */
int IupNewFileDlgOpen(void);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,97 @@
/** \file
* \brief OpenGL canvas for Iup.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPGL_H
#define __IUPGL_H
#ifdef __cplusplus
extern "C" {
#endif
/* Attributes
** To set the appropriate visual (pixel format) the following
** attributes may be specified. Their values should be set
** before the canvas is mapped to the scrren.
** After mapping, changing their values has no effect.
*/
#ifndef IUP_BUFFER /* IUP_SINGLE (defaut) or IUP_DOUBLE */
#define IUP_BUFFER "BUFFER"
#endif
#ifndef IUP_STEREO /* IUP_NO (defaut) or IUP_YES */
#define IUP_STEREO "STEREO"
#endif
#ifndef IUP_BUFFER_SIZE /* Number of bits if index mode */
#define IUP_BUFFER_SIZE "BUFFER_SIZE"
#endif
#ifndef IUP_RED_SIZE /* Number of red bits */
#define IUP_RED_SIZE "RED_SIZE"
#endif
#ifndef IUP_GREEN_SIZE /* Number of green bits */
#define IUP_GREEN_SIZE "GREEN_SIZE"
#endif
#ifndef IUP_BLUE_SIZE /* Number of blue bits */
#define IUP_BLUE_SIZE "BLUE_SIZE"
#endif
#ifndef IUP_ALPHA_SIZE /* Number of alpha bits */
#define IUP_ALPHA_SIZE "ALPHA_SIZE"
#endif
#ifndef IUP_DEPTH_SIZE /* Number of bits in depth buffer */
#define IUP_DEPTH_SIZE "DEPTH_SIZE"
#endif
#ifndef IUP_STENCIL_SIZE /* Number of bits in stencil buffer */
#define IUP_STENCIL_SIZE "STENCIL_SIZE"
#endif
#ifndef IUP_ACCUM_RED_SIZE /* Number of red bits in accum. buffer */
#define IUP_ACCUM_RED_SIZE "ACCUM_RED_SIZE"
#endif
#ifndef IUP_ACCUM_GREEN_SIZE /* Number of green bits in accum. buffer */
#define IUP_ACCUM_GREEN_SIZE "ACCUM_GREEN_SIZE"
#endif
#ifndef IUP_ACCUM_BLUE_SIZE /* Number of blue bits in accum. buffer */
#define IUP_ACCUM_BLUE_SIZE "ACCUM_BLUE_SIZE"
#endif
#ifndef IUP_ACCUM_ALPHA_SIZE /* Number of alpha bits in accum. buffer */
#define IUP_ACCUM_ALPHA_SIZE "ACCUM_ALPHA_SIZE"
#endif
/* Attribute values */
#ifndef IUP_DOUBLE
#define IUP_DOUBLE "DOUBLE"
#endif
#ifndef IUP_SINGLE
#define IUP_SINGLE "SINGLE"
#endif
#ifndef IUP_INDEX
#define IUP_INDEX "INDEX"
#endif
#ifndef IUP_RGBA
#define IUP_RGBA "RGBA"
#endif
#ifndef IUP_YES
#define IUP_YES "YES"
#endif
#ifndef IUP_NO
#define IUP_NO "NO"
#endif
void IupGLCanvasOpen(void);
Ihandle *IupGLCanvas(const char *action);
Ihandle* IupGLBackgroundBox(Ihandle* child);
void IupGLMakeCurrent(Ihandle* ih);
int IupGLIsCurrent(Ihandle* ih);
void IupGLSwapBuffers(Ihandle* ih);
void IupGLPalette(Ihandle* ih, int index, float r, float g, float b);
void IupGLUseFont(Ihandle* ih, int first, int count, int list_base);
void IupGLWait(int gl);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,47 @@
/** \file
* \brief GL Controls.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPGLCONTROLS_H
#define __IUPGLCONTROLS_H
#ifdef __cplusplus
extern "C" {
#endif
int IupGLControlsOpen(void);
Ihandle* IupGLCanvasBoxv(Ihandle** children);
Ihandle* IupGLCanvasBox(Ihandle* child, ...);
Ihandle* IupGLSubCanvas(void);
Ihandle* IupGLLabel(const char* title);
Ihandle* IupGLSeparator(void);
Ihandle* IupGLButton(const char* title);
Ihandle* IupGLToggle(const char* title);
Ihandle* IupGLLink(const char *url, const char * title);
Ihandle* IupGLProgressBar(void);
Ihandle* IupGLVal(void);
Ihandle* IupGLFrame(Ihandle* child);
Ihandle* IupGLExpander(Ihandle* child);
Ihandle* IupGLScrollBox(Ihandle* child);
Ihandle* IupGLSizeBox(Ihandle* child);
Ihandle* IupGLText(void);
/* Utilities */
void IupGLDrawImage(Ihandle* ih, const char* name, int x, int y, int active);
void IupGLDrawText(Ihandle* ih, const char* str, int len, int x, int y);
void IupGLDrawGetTextSize(Ihandle* ih, const char* str, int *w, int *h);
void IupGLDrawGetImageInfo(const char* name, int *w, int *h, int *bpp);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,36 @@
/** \file
* \brief Utilities using IM
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPIM_H
#define __IUPIM_H
#if defined(__cplusplus)
extern "C" {
#endif
void IupImOpen(void); /* optional */
Ihandle* IupLoadImage(const char* filename);
int IupSaveImage(Ihandle* ih, const char* filename, const char* format);
Ihandle* IupLoadAnimation(const char* filename);
Ihandle* IupLoadAnimationFrames(const char** filename_list, int file_count);
#ifdef __IM_IMAGE_H
imImage* IupGetNativeHandleImage(void* handle);
void* IupGetImageNativeHandle(const imImage* image);
Ihandle* IupImageFromImImage(const imImage* image);
imImage* IupImageToImImage(Ihandle* iup_image);
#endif
#if defined(__cplusplus)
}
#endif
#endif
@@ -0,0 +1,533 @@
/** \file
* \brief Keyboard Keys definitions.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPKEY_H
#define __IUPKEY_H
/* from 32 to 126, all character sets are equal,
the key code is the same as the ASCii character code. */
#define K_SP ' ' /* 32 (0x20) */
#define K_exclam '!' /* 33 */
#define K_quotedbl '\"' /* 34 */
#define K_numbersign '#' /* 35 */
#define K_dollar '$' /* 36 */
#define K_percent '%' /* 37 */
#define K_ampersand '&' /* 38 */
#define K_apostrophe '\'' /* 39 */
#define K_parentleft '(' /* 40 */
#define K_parentright ')' /* 41 */
#define K_asterisk '*' /* 42 */
#define K_plus '+' /* 43 */
#define K_comma ',' /* 44 */
#define K_minus '-' /* 45 */
#define K_period '.' /* 46 */
#define K_slash '/' /* 47 */
#define K_0 '0' /* 48 (0x30) */
#define K_1 '1' /* 49 */
#define K_2 '2' /* 50 */
#define K_3 '3' /* 51 */
#define K_4 '4' /* 52 */
#define K_5 '5' /* 53 */
#define K_6 '6' /* 54 */
#define K_7 '7' /* 55 */
#define K_8 '8' /* 56 */
#define K_9 '9' /* 57 */
#define K_colon ':' /* 58 */
#define K_semicolon ';' /* 59 */
#define K_less '<' /* 60 */
#define K_equal '=' /* 61 */
#define K_greater '>' /* 62 */
#define K_question '?' /* 63 */
#define K_at '@' /* 64 */
#define K_A 'A' /* 65 (0x41) */
#define K_B 'B' /* 66 */
#define K_C 'C' /* 67 */
#define K_D 'D' /* 68 */
#define K_E 'E' /* 69 */
#define K_F 'F' /* 70 */
#define K_G 'G' /* 71 */
#define K_H 'H' /* 72 */
#define K_I 'I' /* 73 */
#define K_J 'J' /* 74 */
#define K_K 'K' /* 75 */
#define K_L 'L' /* 76 */
#define K_M 'M' /* 77 */
#define K_N 'N' /* 78 */
#define K_O 'O' /* 79 */
#define K_P 'P' /* 80 */
#define K_Q 'Q' /* 81 */
#define K_R 'R' /* 82 */
#define K_S 'S' /* 83 */
#define K_T 'T' /* 84 */
#define K_U 'U' /* 85 */
#define K_V 'V' /* 86 */
#define K_W 'W' /* 87 */
#define K_X 'X' /* 88 */
#define K_Y 'Y' /* 89 */
#define K_Z 'Z' /* 90 */
#define K_bracketleft '[' /* 91 */
#define K_backslash '\\' /* 92 */
#define K_bracketright ']' /* 93 */
#define K_circum '^' /* 94 */
#define K_underscore '_' /* 95 */
#define K_grave '`' /* 96 */
#define K_a 'a' /* 97 (0x61) */
#define K_b 'b' /* 98 */
#define K_c 'c' /* 99 */
#define K_d 'd' /* 100 */
#define K_e 'e' /* 101 */
#define K_f 'f' /* 102 */
#define K_g 'g' /* 103 */
#define K_h 'h' /* 104 */
#define K_i 'i' /* 105 */
#define K_j 'j' /* 106 */
#define K_k 'k' /* 107 */
#define K_l 'l' /* 108 */
#define K_m 'm' /* 109 */
#define K_n 'n' /* 110 */
#define K_o 'o' /* 111 */
#define K_p 'p' /* 112 */
#define K_q 'q' /* 113 */
#define K_r 'r' /* 114 */
#define K_s 's' /* 115 */
#define K_t 't' /* 116 */
#define K_u 'u' /* 117 */
#define K_v 'v' /* 118 */
#define K_w 'w' /* 119 */
#define K_x 'x' /* 120 */
#define K_y 'y' /* 121 */
#define K_z 'z' /* 122 */
#define K_braceleft '{' /* 123 */
#define K_bar '|' /* 124 */
#define K_braceright '}' /* 125 */
#define K_tilde '~' /* 126 (0x7E) */
/* Printable ASCii keys */
#define iup_isprint(_c) ((_c) > 31 && (_c) < 127)
/* also define the escape sequences that have keys associated */
#define K_BS '\b' /* 8 */
#define K_TAB '\t' /* 9 */
#define K_LF '\n' /* 10 (0x0A) not a real key, is a combination of CR with a modifier, just to document */
#define K_CR '\r' /* 13 (0x0D) */
/* backward compatible definitions */
#define K_quoteleft K_grave
#define K_quoteright K_apostrophe
#define isxkey iup_isXkey
/* IUP Extended Key Codes, range start at 128 */
#define iup_isXkey(_c) ((_c) >= 128)
/* These use the same definition as X11 and GDK.
This also means that any X11 or GDK definition can also be used. */
#define K_PAUSE 0xFF13
#define K_ESC 0xFF1B
#define K_HOME 0xFF50
#define K_LEFT 0xFF51
#define K_UP 0xFF52
#define K_RIGHT 0xFF53
#define K_DOWN 0xFF54
#define K_PGUP 0xFF55
#define K_PGDN 0xFF56
#define K_END 0xFF57
#define K_MIDDLE 0xFF0B
#define K_Print 0xFF61
#define K_INS 0xFF63
#define K_Menu 0xFF67
#define K_DEL 0xFFFF
#define K_F1 0xFFBE
#define K_F2 0xFFBF
#define K_F3 0xFFC0
#define K_F4 0xFFC1
#define K_F5 0xFFC2
#define K_F6 0xFFC3
#define K_F7 0xFFC4
#define K_F8 0xFFC5
#define K_F9 0xFFC6
#define K_F10 0xFFC7
#define K_F11 0xFFC8
#define K_F12 0xFFC9
#define K_F13 0xFFCA
#define K_F14 0xFFCB
#define K_F15 0xFFCC
#define K_F16 0xFFCD
#define K_F17 0xFFCE
#define K_F18 0xFFCF
#define K_F19 0xFFD0
#define K_F20 0xFFD1
/* no Shift/Ctrl/Alt */
#define K_LSHIFT 0xFFE1
#define K_RSHIFT 0xFFE2
#define K_LCTRL 0xFFE3
#define K_RCTRL 0xFFE4
#define K_LALT 0xFFE9
#define K_RALT 0xFFEA
#define K_NUM 0xFF7F
#define K_SCROLL 0xFF14
#define K_CAPS 0xFFE5
/* Mac clear button. Value randomly picked trying to avoid clashing with an existing value. */
#define K_CLEAR 0xFFD2
/* Help button if anybody has it. Value randomly picked trying to avoid clashing with an existing value. */
#define K_HELP 0xFFD3
/* Also, these are the same as the Latin-1 definition */
#define K_ccedilla 0x00E7
#define K_Ccedilla 0x00C7
#define K_acute 0x00B4 /* no Shift/Ctrl/Alt */
#define K_diaeresis 0x00A8
/******************************************************/
/* Modifiers use last 4 bits. Since IUP 3.9 */
/* These modifiers definitions are specific to IUP */
/******************************************************/
#define iup_isShiftXkey(_c) (((_c) & 0x10000000) != 0)
#define iup_isCtrlXkey(_c) (((_c) & 0x20000000) != 0)
#define iup_isAltXkey(_c) (((_c) & 0x40000000) != 0)
#define iup_isSysXkey(_c) (((_c) & 0x80000000) != 0)
#define iup_XkeyBase(_c) ((_c) & 0x0FFFFFFF)
#define iup_XkeyShift(_c) ((_c) | 0x10000000) /* Shift */
#define iup_XkeyCtrl(_c) ((_c) | 0x20000000) /* Ctrl */
#define iup_XkeyAlt(_c) ((_c) | 0x40000000) /* Alt */
#define iup_XkeySys(_c) ((_c) | 0x80000000) /* Sys (Win or Apple) - notice that using "int" will display a negative value */
/* These definitions are here for backward compatibility
and to simplify some key combination usage.
But since IUP 3.9, modifiers can be combined with any key
and they can be mixed together. */
#define K_sHOME iup_XkeyShift(K_HOME )
#define K_sUP iup_XkeyShift(K_UP )
#define K_sPGUP iup_XkeyShift(K_PGUP )
#define K_sLEFT iup_XkeyShift(K_LEFT )
#define K_sMIDDLE iup_XkeyShift(K_MIDDLE )
#define K_sRIGHT iup_XkeyShift(K_RIGHT )
#define K_sEND iup_XkeyShift(K_END )
#define K_sDOWN iup_XkeyShift(K_DOWN )
#define K_sPGDN iup_XkeyShift(K_PGDN )
#define K_sINS iup_XkeyShift(K_INS )
#define K_sDEL iup_XkeyShift(K_DEL )
#define K_sSP iup_XkeyShift(K_SP )
#define K_sTAB iup_XkeyShift(K_TAB )
#define K_sCR iup_XkeyShift(K_CR )
#define K_sBS iup_XkeyShift(K_BS )
#define K_sPAUSE iup_XkeyShift(K_PAUSE )
#define K_sESC iup_XkeyShift(K_ESC )
#define K_sCLEAR iup_XkeyShift(K_CLEAR )
#define K_sF1 iup_XkeyShift(K_F1 )
#define K_sF2 iup_XkeyShift(K_F2 )
#define K_sF3 iup_XkeyShift(K_F3 )
#define K_sF4 iup_XkeyShift(K_F4 )
#define K_sF5 iup_XkeyShift(K_F5 )
#define K_sF6 iup_XkeyShift(K_F6 )
#define K_sF7 iup_XkeyShift(K_F7 )
#define K_sF8 iup_XkeyShift(K_F8 )
#define K_sF9 iup_XkeyShift(K_F9 )
#define K_sF10 iup_XkeyShift(K_F10 )
#define K_sF11 iup_XkeyShift(K_F11 )
#define K_sF12 iup_XkeyShift(K_F12 )
#define K_sF13 iup_XkeyShift(K_F13 )
#define K_sF14 iup_XkeyShift(K_F14 )
#define K_sF15 iup_XkeyShift(K_F15 )
#define K_sF16 iup_XkeyShift(K_F16 )
#define K_sF17 iup_XkeyShift(K_F17 )
#define K_sF18 iup_XkeyShift(K_F18 )
#define K_sF19 iup_XkeyShift(K_F19 )
#define K_sF20 iup_XkeyShift(K_F20 )
#define K_sPrint iup_XkeyShift(K_Print )
#define K_sMenu iup_XkeyShift(K_Menu )
#define K_cHOME iup_XkeyCtrl(K_HOME )
#define K_cUP iup_XkeyCtrl(K_UP )
#define K_cPGUP iup_XkeyCtrl(K_PGUP )
#define K_cLEFT iup_XkeyCtrl(K_LEFT )
#define K_cMIDDLE iup_XkeyCtrl(K_MIDDLE )
#define K_cRIGHT iup_XkeyCtrl(K_RIGHT )
#define K_cEND iup_XkeyCtrl(K_END )
#define K_cDOWN iup_XkeyCtrl(K_DOWN )
#define K_cPGDN iup_XkeyCtrl(K_PGDN )
#define K_cINS iup_XkeyCtrl(K_INS )
#define K_cDEL iup_XkeyCtrl(K_DEL )
#define K_cSP iup_XkeyCtrl(K_SP )
#define K_cTAB iup_XkeyCtrl(K_TAB )
#define K_cCR iup_XkeyCtrl(K_CR )
#define K_cBS iup_XkeyCtrl(K_BS )
#define K_cPAUSE iup_XkeyCtrl(K_PAUSE )
#define K_cESC iup_XkeyCtrl(K_ESC )
#define K_cCLEAR iup_XkeyCtrl(K_CLEAR )
#define K_cCcedilla iup_XkeyCtrl(K_Ccedilla)
#define K_cF1 iup_XkeyCtrl(K_F1 )
#define K_cF2 iup_XkeyCtrl(K_F2 )
#define K_cF3 iup_XkeyCtrl(K_F3 )
#define K_cF4 iup_XkeyCtrl(K_F4 )
#define K_cF5 iup_XkeyCtrl(K_F5 )
#define K_cF6 iup_XkeyCtrl(K_F6 )
#define K_cF7 iup_XkeyCtrl(K_F7 )
#define K_cF8 iup_XkeyCtrl(K_F8 )
#define K_cF9 iup_XkeyCtrl(K_F9 )
#define K_cF10 iup_XkeyCtrl(K_F10 )
#define K_cF11 iup_XkeyCtrl(K_F11 )
#define K_cF12 iup_XkeyCtrl(K_F12 )
#define K_cF13 iup_XkeyCtrl(K_F13 )
#define K_cF14 iup_XkeyCtrl(K_F14 )
#define K_cF15 iup_XkeyCtrl(K_F15 )
#define K_cF16 iup_XkeyCtrl(K_F16 )
#define K_cF17 iup_XkeyCtrl(K_F17 )
#define K_cF18 iup_XkeyCtrl(K_F18 )
#define K_cF19 iup_XkeyCtrl(K_F19 )
#define K_cF20 iup_XkeyCtrl(K_F20 )
#define K_cPrint iup_XkeyCtrl(K_Print )
#define K_cMenu iup_XkeyCtrl(K_Menu )
#define K_mHOME iup_XkeyAlt(K_HOME )
#define K_mUP iup_XkeyAlt(K_UP )
#define K_mPGUP iup_XkeyAlt(K_PGUP )
#define K_mLEFT iup_XkeyAlt(K_LEFT )
#define K_mMIDDLE iup_XkeyAlt(K_MIDDLE )
#define K_mRIGHT iup_XkeyAlt(K_RIGHT )
#define K_mEND iup_XkeyAlt(K_END )
#define K_mDOWN iup_XkeyAlt(K_DOWN )
#define K_mPGDN iup_XkeyAlt(K_PGDN )
#define K_mINS iup_XkeyAlt(K_INS )
#define K_mDEL iup_XkeyAlt(K_DEL )
#define K_mSP iup_XkeyAlt(K_SP )
#define K_mTAB iup_XkeyAlt(K_TAB )
#define K_mCR iup_XkeyAlt(K_CR )
#define K_mBS iup_XkeyAlt(K_BS )
#define K_mPAUSE iup_XkeyAlt(K_PAUSE )
#define K_mESC iup_XkeyAlt(K_ESC )
#define K_mCLEAR iup_XkeyAlt(K_CLEAR )
#define K_mCcedilla iup_XkeyAlt(K_Ccedilla)
#define K_mF1 iup_XkeyAlt(K_F1 )
#define K_mF2 iup_XkeyAlt(K_F2 )
#define K_mF3 iup_XkeyAlt(K_F3 )
#define K_mF4 iup_XkeyAlt(K_F4 )
#define K_mF5 iup_XkeyAlt(K_F5 )
#define K_mF6 iup_XkeyAlt(K_F6 )
#define K_mF7 iup_XkeyAlt(K_F7 )
#define K_mF8 iup_XkeyAlt(K_F8 )
#define K_mF9 iup_XkeyAlt(K_F9 )
#define K_mF10 iup_XkeyAlt(K_F10 )
#define K_mF11 iup_XkeyAlt(K_F11 )
#define K_mF12 iup_XkeyAlt(K_F12 )
#define K_mF13 iup_XkeyAlt(K_F13 )
#define K_mF14 iup_XkeyAlt(K_F14 )
#define K_mF15 iup_XkeyAlt(K_F15 )
#define K_mF16 iup_XkeyAlt(K_F16 )
#define K_mF17 iup_XkeyAlt(K_F17 )
#define K_mF18 iup_XkeyAlt(K_F18 )
#define K_mF19 iup_XkeyAlt(K_F19 )
#define K_mF20 iup_XkeyAlt(K_F20 )
#define K_mPrint iup_XkeyAlt(K_Print )
#define K_mMenu iup_XkeyAlt(K_Menu )
#define K_yHOME iup_XkeySys(K_HOME )
#define K_yUP iup_XkeySys(K_UP )
#define K_yPGUP iup_XkeySys(K_PGUP )
#define K_yLEFT iup_XkeySys(K_LEFT )
#define K_yMIDDLE iup_XkeySys(K_MIDDLE )
#define K_yRIGHT iup_XkeySys(K_RIGHT )
#define K_yEND iup_XkeySys(K_END )
#define K_yDOWN iup_XkeySys(K_DOWN )
#define K_yPGDN iup_XkeySys(K_PGDN )
#define K_yINS iup_XkeySys(K_INS )
#define K_yDEL iup_XkeySys(K_DEL )
#define K_ySP iup_XkeySys(K_SP )
#define K_yTAB iup_XkeySys(K_TAB )
#define K_yCR iup_XkeySys(K_CR )
#define K_yBS iup_XkeySys(K_BS )
#define K_yPAUSE iup_XkeySys(K_PAUSE )
#define K_yESC iup_XkeySys(K_ESC )
#define K_yCLEAR iup_XkeySys(K_CLEAR )
#define K_yCcedilla iup_XkeySys(K_Ccedilla)
#define K_yF1 iup_XkeySys(K_F1 )
#define K_yF2 iup_XkeySys(K_F2 )
#define K_yF3 iup_XkeySys(K_F3 )
#define K_yF4 iup_XkeySys(K_F4 )
#define K_yF5 iup_XkeySys(K_F5 )
#define K_yF6 iup_XkeySys(K_F6 )
#define K_yF7 iup_XkeySys(K_F7 )
#define K_yF8 iup_XkeySys(K_F8 )
#define K_yF9 iup_XkeySys(K_F9 )
#define K_yF10 iup_XkeySys(K_F10 )
#define K_yF11 iup_XkeySys(K_F11 )
#define K_yF12 iup_XkeySys(K_F12 )
#define K_yF13 iup_XkeySys(K_F13 )
#define K_yF14 iup_XkeySys(K_F14 )
#define K_yF15 iup_XkeySys(K_F15 )
#define K_yF16 iup_XkeySys(K_F16 )
#define K_yF17 iup_XkeySys(K_F17 )
#define K_yF18 iup_XkeySys(K_F18 )
#define K_yF19 iup_XkeySys(K_F19 )
#define K_yF20 iup_XkeySys(K_F20 )
#define K_yPrint iup_XkeySys(K_Print )
#define K_yMenu iup_XkeySys(K_Menu )
#define K_sPlus iup_XkeyShift(K_plus )
#define K_sComma iup_XkeyShift(K_comma )
#define K_sMinus iup_XkeyShift(K_minus )
#define K_sPeriod iup_XkeyShift(K_period )
#define K_sSlash iup_XkeyShift(K_slash )
#define K_sAsterisk iup_XkeyShift(K_asterisk)
#define K_cA iup_XkeyCtrl(K_A)
#define K_cB iup_XkeyCtrl(K_B)
#define K_cC iup_XkeyCtrl(K_C)
#define K_cD iup_XkeyCtrl(K_D)
#define K_cE iup_XkeyCtrl(K_E)
#define K_cF iup_XkeyCtrl(K_F)
#define K_cG iup_XkeyCtrl(K_G)
#define K_cH iup_XkeyCtrl(K_H)
#define K_cI iup_XkeyCtrl(K_I)
#define K_cJ iup_XkeyCtrl(K_J)
#define K_cK iup_XkeyCtrl(K_K)
#define K_cL iup_XkeyCtrl(K_L)
#define K_cM iup_XkeyCtrl(K_M)
#define K_cN iup_XkeyCtrl(K_N)
#define K_cO iup_XkeyCtrl(K_O)
#define K_cP iup_XkeyCtrl(K_P)
#define K_cQ iup_XkeyCtrl(K_Q)
#define K_cR iup_XkeyCtrl(K_R)
#define K_cS iup_XkeyCtrl(K_S)
#define K_cT iup_XkeyCtrl(K_T)
#define K_cU iup_XkeyCtrl(K_U)
#define K_cV iup_XkeyCtrl(K_V)
#define K_cW iup_XkeyCtrl(K_W)
#define K_cX iup_XkeyCtrl(K_X)
#define K_cY iup_XkeyCtrl(K_Y)
#define K_cZ iup_XkeyCtrl(K_Z)
#define K_c1 iup_XkeyCtrl(K_1)
#define K_c2 iup_XkeyCtrl(K_2)
#define K_c3 iup_XkeyCtrl(K_3)
#define K_c4 iup_XkeyCtrl(K_4)
#define K_c5 iup_XkeyCtrl(K_5)
#define K_c6 iup_XkeyCtrl(K_6)
#define K_c7 iup_XkeyCtrl(K_7)
#define K_c8 iup_XkeyCtrl(K_8)
#define K_c9 iup_XkeyCtrl(K_9)
#define K_c0 iup_XkeyCtrl(K_0)
#define K_cPlus iup_XkeyCtrl(K_plus )
#define K_cComma iup_XkeyCtrl(K_comma )
#define K_cMinus iup_XkeyCtrl(K_minus )
#define K_cPeriod iup_XkeyCtrl(K_period )
#define K_cSlash iup_XkeyCtrl(K_slash )
#define K_cSemicolon iup_XkeyCtrl(K_semicolon )
#define K_cEqual iup_XkeyCtrl(K_equal )
#define K_cBracketleft iup_XkeyCtrl(K_bracketleft )
#define K_cBracketright iup_XkeyCtrl(K_bracketright)
#define K_cBackslash iup_XkeyCtrl(K_backslash )
#define K_cAsterisk iup_XkeyCtrl(K_asterisk )
#define K_mA iup_XkeyAlt(K_A)
#define K_mB iup_XkeyAlt(K_B)
#define K_mC iup_XkeyAlt(K_C)
#define K_mD iup_XkeyAlt(K_D)
#define K_mE iup_XkeyAlt(K_E)
#define K_mF iup_XkeyAlt(K_F)
#define K_mG iup_XkeyAlt(K_G)
#define K_mH iup_XkeyAlt(K_H)
#define K_mI iup_XkeyAlt(K_I)
#define K_mJ iup_XkeyAlt(K_J)
#define K_mK iup_XkeyAlt(K_K)
#define K_mL iup_XkeyAlt(K_L)
#define K_mM iup_XkeyAlt(K_M)
#define K_mN iup_XkeyAlt(K_N)
#define K_mO iup_XkeyAlt(K_O)
#define K_mP iup_XkeyAlt(K_P)
#define K_mQ iup_XkeyAlt(K_Q)
#define K_mR iup_XkeyAlt(K_R)
#define K_mS iup_XkeyAlt(K_S)
#define K_mT iup_XkeyAlt(K_T)
#define K_mU iup_XkeyAlt(K_U)
#define K_mV iup_XkeyAlt(K_V)
#define K_mW iup_XkeyAlt(K_W)
#define K_mX iup_XkeyAlt(K_X)
#define K_mY iup_XkeyAlt(K_Y)
#define K_mZ iup_XkeyAlt(K_Z)
#define K_m1 iup_XkeyAlt(K_1)
#define K_m2 iup_XkeyAlt(K_2)
#define K_m3 iup_XkeyAlt(K_3)
#define K_m4 iup_XkeyAlt(K_4)
#define K_m5 iup_XkeyAlt(K_5)
#define K_m6 iup_XkeyAlt(K_6)
#define K_m7 iup_XkeyAlt(K_7)
#define K_m8 iup_XkeyAlt(K_8)
#define K_m9 iup_XkeyAlt(K_9)
#define K_m0 iup_XkeyAlt(K_0)
#define K_mPlus iup_XkeyAlt(K_plus )
#define K_mComma iup_XkeyAlt(K_comma )
#define K_mMinus iup_XkeyAlt(K_minus )
#define K_mPeriod iup_XkeyAlt(K_period )
#define K_mSlash iup_XkeyAlt(K_slash )
#define K_mSemicolon iup_XkeyAlt(K_semicolon )
#define K_mEqual iup_XkeyAlt(K_equal )
#define K_mBracketleft iup_XkeyAlt(K_bracketleft )
#define K_mBracketright iup_XkeyAlt(K_bracketright)
#define K_mBackslash iup_XkeyAlt(K_backslash )
#define K_mAsterisk iup_XkeyAlt(K_asterisk )
#define K_yA iup_XkeySys(K_A)
#define K_yB iup_XkeySys(K_B)
#define K_yC iup_XkeySys(K_C)
#define K_yD iup_XkeySys(K_D)
#define K_yE iup_XkeySys(K_E)
#define K_yF iup_XkeySys(K_F)
#define K_yG iup_XkeySys(K_G)
#define K_yH iup_XkeySys(K_H)
#define K_yI iup_XkeySys(K_I)
#define K_yJ iup_XkeySys(K_J)
#define K_yK iup_XkeySys(K_K)
#define K_yL iup_XkeySys(K_L)
#define K_yM iup_XkeySys(K_M)
#define K_yN iup_XkeySys(K_N)
#define K_yO iup_XkeySys(K_O)
#define K_yP iup_XkeySys(K_P)
#define K_yQ iup_XkeySys(K_Q)
#define K_yR iup_XkeySys(K_R)
#define K_yS iup_XkeySys(K_S)
#define K_yT iup_XkeySys(K_T)
#define K_yU iup_XkeySys(K_U)
#define K_yV iup_XkeySys(K_V)
#define K_yW iup_XkeySys(K_W)
#define K_yX iup_XkeySys(K_X)
#define K_yY iup_XkeySys(K_Y)
#define K_yZ iup_XkeySys(K_Z)
#define K_y1 iup_XkeySys(K_1)
#define K_y2 iup_XkeySys(K_2)
#define K_y3 iup_XkeySys(K_3)
#define K_y4 iup_XkeySys(K_4)
#define K_y5 iup_XkeySys(K_5)
#define K_y6 iup_XkeySys(K_6)
#define K_y7 iup_XkeySys(K_7)
#define K_y8 iup_XkeySys(K_8)
#define K_y9 iup_XkeySys(K_9)
#define K_y0 iup_XkeySys(K_0)
#define K_yPlus iup_XkeySys(K_plus )
#define K_yComma iup_XkeySys(K_comma )
#define K_yMinus iup_XkeySys(K_minus )
#define K_yPeriod iup_XkeySys(K_period )
#define K_ySlash iup_XkeySys(K_slash )
#define K_ySemicolon iup_XkeySys(K_semicolon )
#define K_yEqual iup_XkeySys(K_equal )
#define K_yBracketleft iup_XkeySys(K_bracketleft )
#define K_yBracketright iup_XkeySys(K_bracketright)
#define K_yBackslash iup_XkeySys(K_backslash )
#define K_yAsterisk iup_XkeySys(K_asterisk )
#endif
@@ -0,0 +1,54 @@
/** \file
* \brief IUP Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUA_H
#define __IUPLUA_H
#ifdef __cplusplus
extern "C" {
#endif
#ifndef DOXYGEN_SHOULD_IGNORE_THIS
/** @cond DOXYGEN_SHOULD_IGNORE_THIS */
#ifndef IUPLUA_API
#ifdef IUPLUA_BUILD_LIBRARY
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#define IUPLUA_API EMSCRIPTEN_KEEPALIVE
#elif WIN32
#define IUPLUA_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define IUPLUA_API __attribute__ ((visibility("default")))
#else
#define IUPLUA_API
#endif
#else
#define IUPLUA_API
#endif /* IUPLUA_BUILD_LIBRARY */
#endif /* IUPLUA_API */
/** @endcond DOXYGEN_SHOULD_IGNORE_THIS */
#endif /* DOXYGEN_SHOULD_IGNORE_THIS */
IUPLUA_API int iuplua_open(lua_State *L);
IUPLUA_API int iupkey_open(lua_State *L); /* does nothing, kept for backward compatibility */
IUPLUA_API int iuplua_close(lua_State * L);
/* utilities */
IUPLUA_API int iuplua_isihandle(lua_State *L, int pos);
IUPLUA_API Ihandle* iuplua_checkihandle(lua_State *L, int pos);
IUPLUA_API void iuplua_pushihandle(lua_State *L, Ihandle *n);
IUPLUA_API int iuplua_dofile(lua_State *L, const char *filename);
IUPLUA_API int iuplua_dostring(lua_State *L, const char *string, const char *chunk_name);
IUPLUA_API int iuplua_dobuffer(lua_State *L, const char *buffer, int len, const char *chunk_name);
IUPLUA_API void iuplua_show_error_message(const char *pname, const char* msg);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief IupMglPlot Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUA_MGLPLOT_H
#define __IUPLUA_MGLPLOT_H
#ifdef __cplusplus
extern "C" {
#endif
int iup_mglplotlua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief iup_plot Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUA_PLOT_H
#define __IUPLUA_PLOT_H
#ifdef __cplusplus
extern "C" {
#endif
int iup_plotlua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief IupScintilla Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUA_SCINTILLA_H
#define __IUPLUA_SCINTILLA_H
#ifdef __cplusplus
extern "C" {
#endif
int iup_scintillalua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief iupcontrols Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUACONTROLS_H
#define __IUPLUACONTROLS_H
#ifdef __cplusplus
extern "C" {
#endif
int iupcontrolslua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief Binding of new iupfiledlg to Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUAFILEDLG_H
#define __IUPLUAFILEDLG_H
#ifdef __cplusplus
extern "C" {
#endif
int iupfiledlglua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief Binding of iupglcanvas to Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUAGL_H
#define __IUPLUAGL_H
#ifdef __cplusplus
extern "C" {
#endif
int iupgllua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief iupglcontrols Binding for Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUAGLCONTROLS_H
#define __IUPLUAGLCONTROLS_H
#ifdef __cplusplus
extern "C" {
#endif
int iupglcontrolslua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif
@@ -0,0 +1,20 @@
/** \file
* \brief Bindig of iupim functions to Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUAIM_H
#define __IUPLUAIM_H
#ifdef __cplusplus
extern "C" {
#endif
int iupimlua_open(lua_State * L);
#ifdef __cplusplus
}
#endif
#endif

Some files were not shown because too many files have changed in this diff Show More