27 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
Serendipity 17d7079c41 从GitHub仓库中移除CSV游戏记录文件\n\n- 在.gitignore中添加*.csv规则\n- 从版本控制中移除所有CSV文件\n- 本地文件保留,但不再跟踪 2025-10-08 00:57:54 +08:00
Serendipity 1abde99a68 v8.2: 完善专业安装包制作功能\n\n- 支持Inno Setup和NSIS双重安装包方案\n- 完整的软件分发体系\n- 一键安装部署和完整卸载功能\n- 更新所有文档以反映v8.2版本特性 2025-10-08 00:54:56 +08:00
Serendipity 205e943bcb 重构项目结构:将源文件和头文件分别移动到src和include目录 2025-09-22 22:53:14 +08:00
Serendipity ae0629ef6e feat: v8.2版本更新 - 编译脚本优化\n\n- 🔧 交互式编译脚本:compile_gui.bat支持选择编译控制台或GUI版本\n- 📋 用户友好界面:提供清晰的编译选项菜单和操作指引\n- 编译流程优化:统一编译参数,解决SDL3依赖问题\n- �� 多语言支持:英文界面避免编码问题,确保兼容性\n- 错误处理完善:添加无效输入处理和详细错误提示\n- 🎯 开发体验提升:简化编译流程,提高开发效率 2025-09-20 11:08:46 +08:00
Serendipity 2121831478 Merge branch 'main' of https://github.com/LHY0125/Gobang-Game 2025-09-20 10:52:28 +08:00
Serendipity a11ddeb8d1 feat: 添加Makefile编译系统和BUILD文档
- 创建完整的Makefile支持make编译
- 支持编译控制台版本和GUI版本
- 添加清理、运行、帮助等目标
- 自动处理SDL3和网络库依赖
- 创建BUILD.md编译指南文档
- 完善GUI相关全局变量管理
- 丰富函数注释和文档
2025-09-20 10:50:58 +08:00
Serendipity 39d84f38cf Update README.md 2025-09-18 19:23:18 +08:00
Serendipity 198a8a2943 Update README.md 2025-09-18 19:22:46 +08:00
Serendipity 0e53b09d9b v8.0版本更新:添加SDL3图形化界面功能和完善文档 2025-09-18 19:08:37 +08:00
Serendipity 1d8e2e25cf 重构安装脚本:将安装文件移动到installer文件夹并修复路径问题 2025-07-27 20:22:52 +08:00
Serendipity 6d4de737c4 Add NSIS installer script and update main.c 2025-07-27 10:34:49 +08:00
Serendipity b413f7254a Update main.c and add project requirements 2025-07-24 10:27:18 +08:00
Serendipity cb81105809 代码格式化和优化:统一换行符格式,优化代码结构 2025-07-23 10:09:02 +08:00
Serendipity fbe4f5273c 重构输入处理:统一使用get_integer_input函数替换scanf 2025-07-23 09:37:54 +08:00
Serendipity 59c816767b 更新项目结构:移除icon文件夹,添加图标指南文档,更新.gitignore 2025-07-21 12:43:52 +08:00
Serendipity 504868c739 优化AI参数配置:使用DEFAULT_DEFENSE_COEFFICIENT并更新相关注释 2025-07-21 00:18:11 +08:00
162 changed files with 17749 additions and 4470 deletions
+7 -9
View File
@@ -1,5 +1,4 @@
# 编译生成的可执行文件 # 编译生成的可执行文件
*.exe
*.out *.out
*.app *.app
@@ -29,14 +28,13 @@ Thumbs.db
*.ilk *.ilk
# 对象文件 # 对象文件
*.o
*.obj *.obj
# 静态库文件 # 打包文件
*.lib dist/
*.a
# 动态库文件 # 编译生成的对象文件
*.dll obj/
*.so
*.dylib # 临时游戏存档
records/
-461
View File
@@ -1,461 +0,0 @@
# 🚀 五子棋AI增强指南
## 📋 概述
本文档详细介绍了提升五子棋AI水平的各种方法和实现策略,基于当前项目的代码架构,提供从简单参数调优到复杂算法改进的完整方案。
## 🎯 当前AI分析
### 现有优势
- ✅ 模块化设计良好
- ✅ 基础Minimax + α-β剪枝算法
- ✅ 完整的棋型评估系统
- ✅ 威胁检测机制
- ✅ 防御优先策略
### 改进空间
- 🔄 搜索深度有限(当前3层)
- 🔄 评估函数相对简单
- 🔄 缺乏开局库和残局库
- 🔄 没有学习机制
- 🔄 搜索效率可优化
## 🛠️ 改进方案
### 1. 立即可实施的改进(难度:⭐)
#### 1.1 参数调优
**修改 `config.h` 中的关键参数:**
```c
// 增加搜索深度
#define DEFAULT_AI_DEPTH 5 // 从3提升到5
// 优化防守系数
#define DEFAULT_DEFENSE_COEFFICIENT 1.5 // 从1.2提升到1.5
// 扩大搜索范围
#define AI_NEARBY_RANGE 3 // 从2扩大到3
// 降低搜索范围限制阈值
#define AI_SEARCH_RANGE_THRESHOLD 8 // 从10降低到8
```
#### 1.2 评分系统优化
**在 `config.h` 中添加新的评分项:**
```c
// 组合棋型评分
#define AI_SCORE_DOUBLE_THREE 50000 // 双三
#define AI_SCORE_FOUR_THREE 200000 // 四三
#define AI_SCORE_THREAT_SEQUENCE 80000 // 威胁序列
#define AI_SCORE_POTENTIAL_FIVE 300000 // 潜在五连
```
### 2. 短期改进(1-2周,难度:⭐⭐)
#### 2.1 移动排序优化
**在 `ai.c` 中添加移动排序函数:**
```c
// 移动排序结构
typedef struct {
int x, y;
int score;
} ScoredMove;
// 移动排序函数
int compare_moves(const void *a, const void *b) {
ScoredMove *moveA = (ScoredMove*)a;
ScoredMove *moveB = (ScoredMove*)b;
return moveB->score - moveA->score;
}
// 生成并排序候选移动
int generate_candidate_moves(ScoredMove *moves, int player) {
int count = 0;
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] == EMPTY && is_near_stones(i, j)) {
moves[count].x = i;
moves[count].y = j;
moves[count].score = evaluate_move(i, j);
count++;
}
}
}
qsort(moves, count, sizeof(ScoredMove), compare_moves);
return count;
}
```
#### 2.2 威胁检测增强
**添加多层次威胁检测:**
```c
// 威胁类型枚举
typedef enum {
THREAT_NONE = 0,
THREAT_WIN = 5, // 直接获胜
THREAT_FOUR = 4, // 活四/冲四
THREAT_THREE = 3, // 活三
THREAT_DOUBLE = 2, // 双威胁
THREAT_POTENTIAL = 1 // 潜在威胁
} ThreatLevel;
// 威胁检测函数
ThreatLevel detect_threat(int x, int y, int player) {
// 实现威胁检测逻辑
// ...
}
```
### 3. 中期改进(1-2月,难度:⭐⭐⭐)
#### 3.1 置换表实现
**添加置换表缓存系统:**
```c
// 置换表项
typedef struct {
uint64_t hash_key; // 棋盘哈希值
int score; // 评估分数
int depth; // 搜索深度
int best_x, best_y; // 最佳移动
int flag; // 节点类型(精确值/上界/下界)
} TranspositionEntry;
// 置换表
#define TT_SIZE 1048576 // 2^20
TranspositionEntry transposition_table[TT_SIZE];
// 棋盘哈希函数
uint64_t zobrist_hash() {
// 实现Zobrist哈希
// ...
}
```
#### 3.2 开局库系统
**创建开局库数据结构:**
```c
// 开局库项
typedef struct {
int moves[20][2]; // 开局移动序列
int move_count; // 移动数量
int win_rate; // 胜率
char name[50]; // 开局名称
} OpeningEntry;
// 开局库
OpeningEntry opening_book[] = {
// 天元开局
{{{7,7}, {6,6}, {8,8}, {6,8}, {8,6}}, 5, 65, "天元开局"},
// 花月开局
{{{7,7}, {6,7}, {8,7}, {7,6}, {7,8}}, 5, 70, "花月开局"},
// 更多开局...
};
```
#### 3.3 改进的评估函数
**实现更复杂的位置评估:**
```c
// 高级评估函数
int advanced_evaluate_pos(int x, int y, int player) {
int score = 0;
// 1. 基础棋型评分
score += basic_pattern_score(x, y, player);
// 2. 组合棋型评分
score += combination_pattern_score(x, y, player);
// 3. 位置价值评分
score += positional_value_score(x, y);
// 4. 威胁序列评分
score += threat_sequence_score(x, y, player);
// 5. 防守价值评分
score += defensive_value_score(x, y, player);
return score;
}
```
### 4. 长期改进(3-6月,难度:⭐⭐⭐⭐)
#### 4.1 蒙特卡洛树搜索(MCTS
**MCTS节点结构:**
```c
// MCTS节点
typedef struct MCTSNode {
int x, y; // 移动位置
int visits; // 访问次数
double wins; // 胜利次数
struct MCTSNode *parent; // 父节点
struct MCTSNode **children; // 子节点数组
int child_count; // 子节点数量
bool fully_expanded; // 是否完全展开
} MCTSNode;
// MCTS主函数
int mcts_search(int simulations) {
MCTSNode *root = create_node(-1, -1, NULL);
for (int i = 0; i < simulations; i++) {
MCTSNode *node = selection(root);
node = expansion(node);
double result = simulation(node);
backpropagation(node, result);
}
return best_child(root);
}
```
#### 4.2 神经网络集成
**神经网络评估接口:**
```c
// 神经网络评估函数
float neural_network_evaluate(int board[BOARD_SIZE][BOARD_SIZE]) {
// 调用训练好的神经网络模型
// 返回位置评估值
// ...
}
// 混合评估函数
int hybrid_evaluate(int x, int y, int player) {
// 传统评估
int traditional_score = evaluate_pos(x, y, player);
// 神经网络评估
float nn_score = neural_network_evaluate(board);
// 加权组合
return (int)(0.7 * traditional_score + 0.3 * nn_score * 10000);
}
```
## 📊 性能优化策略
### 1. 搜索优化
#### 1.1 迭代加深搜索
```c
int iterative_deepening_search(int max_depth, int time_limit) {
int best_move = -1;
clock_t start_time = clock();
for (int depth = 1; depth <= max_depth; depth++) {
if ((clock() - start_time) * 1000 / CLOCKS_PER_SEC > time_limit) {
break;
}
best_move = alpha_beta_search(depth);
}
return best_move;
}
```
#### 1.2 空窗搜索
```c
int null_window_search(int depth, int beta) {
return alpha_beta_search(depth, beta - 1, beta);
}
```
### 2. 内存优化
#### 2.1 位棋盘表示
```c
// 使用位操作优化棋盘表示
typedef struct {
uint64_t player1_board[4]; // 玩家1的棋盘(4个64位整数)
uint64_t player2_board[4]; // 玩家2的棋盘
} BitBoard;
```
## 🎮 实战策略
### 1. 自适应难度系统
```c
// 难度等级
typedef enum {
DIFFICULTY_EASY = 1,
DIFFICULTY_NORMAL = 2,
DIFFICULTY_HARD = 3,
DIFFICULTY_EXPERT = 4,
DIFFICULTY_MASTER = 5
} DifficultyLevel;
// 根据难度调整AI参数
void adjust_ai_parameters(DifficultyLevel level) {
switch (level) {
case DIFFICULTY_EASY:
ai_depth = 2;
defense_coefficient = 1.0;
break;
case DIFFICULTY_NORMAL:
ai_depth = 3;
defense_coefficient = 1.2;
break;
case DIFFICULTY_HARD:
ai_depth = 4;
defense_coefficient = 1.5;
break;
// ...
}
}
```
### 2. 学习系统
```c
// 对局记录
typedef struct {
int moves[MAX_STEPS][2];
int move_count;
int winner;
int ai_mistakes;
float game_quality;
} GameRecord;
// 学习函数
void learn_from_game(GameRecord *record) {
// 分析对局,更新评估参数
// 识别AI的错误决策
// 调整相关参数
}
```
## 📈 测试与评估
### 1. 性能测试
```c
// 性能测试函数
void performance_test() {
clock_t start = clock();
// 执行1000次AI决策
for (int i = 0; i < 1000; i++) {
ai_move(DEFAULT_AI_DEPTH);
// 重置棋盘
}
clock_t end = clock();
double time_taken = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("平均决策时间: %.2f ms\n", time_taken);
}
```
### 2. 棋力测试
```c
// 自我对弈测试
int self_play_test(int games) {
int wins = 0;
for (int i = 0; i < games; i++) {
// AI vs AI(不同版本或参数)
int result = play_game();
if (result == 1) wins++;
}
return (wins * 100) / games; // 胜率
}
```
## 🚀 实施路线图
### 阶段1:基础优化(1周)
- [ ] 调整搜索深度和评分参数
- [ ] 优化移动排序
- [ ] 增强威胁检测
### 阶段2:算法改进(2-4周)
- [ ] 实现置换表
- [ ] 添加开局库
- [ ] 改进评估函数
### 阶段3:高级功能(1-2月)
- [ ] 实现MCTS
- [ ] 添加学习机制
- [ ] 性能优化
### 阶段4AI增强(2-3月)
- [ ] 神经网络集成
- [ ] 并行搜索
- [ ] 完整的自适应系统
## 📚 参考资源
### 算法资料
- 《人工智能:一种现代方法》- Stuart Russell
- 《游戏编程中的人工智能技术》- Mat Buckland
- AlphaGo论文系列
### 开源项目
- Stockfish(国际象棋引擎)
- Leela Zero(围棋AI
- Gomoku AI项目
### 在线资源
- Chess Programming Wiki
- Computer Olympiad
- AI游戏编程社区
## 🏗️ 代码架构优化 (v7.0新增)
### 配置管理统一化
在v7.0版本中,我们完成了重要的代码架构重构:
#### 配置参数集中管理
- **统一配置文件**:所有AI相关参数现在集中在`config.h`中定义
- **参数分类管理**:AI参数按功能分组(搜索深度、评分权重、时间限制等)
- **配置文件支持**AI参数可通过`gobang_config.ini`文件动态调整
- **运行时修改**:支持游戏过程中实时调整AI难度和参数
#### 代码模块化优化
- **清晰的模块分离**:AI逻辑与游戏逻辑完全分离
- **接口标准化**:统一的AI接口设计,便于算法替换和升级
- **全局变量管理**:AI相关全局变量集中在`globals`模块中
- **类型定义统一**:所有数据结构定义集中在`type.h`
#### 维护性提升
- **宏定义优化**:消除重复定义,提高代码一致性
- **注释规范化**:完善的代码注释和文档
- **错误处理统一**:标准化的错误处理机制
- **调试支持增强**:更好的调试信息和日志记录
这些架构优化为后续的AI算法改进奠定了坚实的基础,使得实施复杂的AI增强方案变得更加容易和可靠。
## 💡 总结
通过系统性的改进,可以将当前的五子棋AI从业余水平提升到接近专业水平。关键是要循序渐进,先实施简单的改进,再逐步引入复杂的算法。每个阶段都要进行充分的测试和评估,确保改进的有效性。
建议按照优先级顺序实施:
1. **短期目标**:参数调优 + 开局库 + 棋型优化
2. **中期目标**:搜索算法优化 + 评估函数改进
3. **长期目标**:机器学习集成 + MCTS实现
v7.0的架构重构为所有这些改进提供了更好的代码基础。
记住:**好的AI不仅要算得深,更要算得准!**
-147
View File
@@ -1,147 +0,0 @@
# 🧠 五子棋AI实现详解
## 📜 算法概述
本五子棋AI采用α-β剪枝优化的极小极大算法,结合专业的棋型评估系统和多层次的威胁检测机制。支持人机对战、双人对战和网络对战多种模式。
```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);
```
## ⚙️ 核心函数
### 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难度动态调整
```
-268
View File
@@ -1,268 +0,0 @@
# 五子棋项目代码架构重构指南
## 📋 概述
本文档详细记录了五子棋项目在v7.0版本中进行的重大代码架构重构,包括重构的目标、实施过程、技术细节和带来的改进。
## 🎯 重构目标
### 主要目标
1. **代码模块化** - 实现清晰的模块分离和职责划分
2. **配置统一管理** - 集中管理所有配置参数和宏定义
3. **全局变量规范化** - 统一管理全局变量,避免散乱分布
4. **类型定义标准化** - 集中定义所有数据结构和类型
5. **提升可维护性** - 降低代码耦合度,提高可读性和可维护性
### 预期收益
- 减少代码重复和冗余
- 提高开发效率和调试便利性
- 增强代码的可扩展性和可移植性
- 为后续功能开发奠定坚实基础
## 🏗️ 重构实施
### 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版本的代码架构重构是一次重要的技术升级,通过系统性的重构实现了:
**配置参数的统一管理** - 提高了配置的一致性和可维护性
**全局变量的规范化** - 降低了代码的复杂度和耦合度
**类型定义的标准化** - 增强了代码的可读性和类型安全
**模块结构的优化** - 为后续功能扩展奠定了坚实基础
这次重构不仅解决了当前的技术债务,更为项目的长期发展提供了良好的架构基础。后续的功能开发将能够更加高效和稳定地进行。
---
*本文档将随着项目的发展持续更新,记录架构演进的每一个重要节点。*
-152
View File
@@ -1,152 +0,0 @@
# 五子棋网络对战使用说明
## 功能概述
本项目支持网络对战功能,允许两台设备通过网络进行实时五子棋对战,支持服务器/客户端连接。
## 编译方法
```bash
gcc -std=c17 -o gobang.exe *.c -lws2_32
```
**注意:**
- Windows系统需要添加 `-lws2_32` 链接库
- Linux系统不需要此链接库参数
## 使用方法
### 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
- 游戏结束后及时关闭程序
- 注意保护个人网络信息
## 更新日志
### v7.0 (2025-07-20)
- 网络配置参数统一管理 - 所有网络相关配置集中到config.h
- 消息类型定义优化 - 统一消息协议宏定义
- 代码架构重构 - 提升网络模块的可维护性
- 配置文件支持 - 网络参数可通过配置文件调整
### v6.1 (2025-07-10)
- 完善网络对战功能
- 支持TCP/IP通信
- 实现棋盘同步
- 连接状态和协议优化
- 支持多种操作
- 添加延时控制等游戏功能(延时显示、认输、悔棋等)
---
**开发者:** 刘航宇
**联系邮箱:** 3364451258@qq.com
**项目主页:** https://github.com/LHY0125/Gobang-Game
+102
View File
@@ -0,0 +1,102 @@
# 五子棋游戏 Makefile
# 支持编译GUI版本 (IUP)
# 编译器设置
CC = gcc
# 显式指定 Shell 为 PowerShell
SHELL = D:/PowerShell/PowerShell-7.5.4/PowerShell.exe
.SHELLFLAGS = -NoProfile -Command
CFLAGS = -Wall -Wextra -std=c17 -O2 -Iinclude -finput-charset=UTF-8 -fexec-charset=UTF-8
# ENet 包含路径
ENET_INC = -Ilibs/enet/include
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_DIR)/gobang.c $(SRC_DIR)/ai.c $(SRC_DIR)/config.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
# ENet 源文件
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_DIR)/%.c,$(OBJ_DIR)/%.o,$(COMMON_SOURCES))
ENET_OBJECTS = $(patsubst libs/enet/%.c,$(OBJ_DIR)/enet_%.o,$(ENET_SOURCES))
# 可执行文件
GUI_TARGET = $(BIN_DIR)/gobang_gui.exe
# 默认目标
all: directories $(GUI_TARGET)
# 创建目录 (PowerShell 语法)
directories:
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_TARGET): $(COMMON_OBJECTS) $(ENET_OBJECTS) $(OBJ_DIR)/main.o
$(CC) $(CFLAGS) $(IUP_INCLUDE) -o $@ $^ $(IUP_LIBS) $(LDFLAGS)
Copy-Item -Path "$(subst /,\,$(IUP_PATH))\iup.dll" -Destination "$(BIN_DIR)" -Force
# 通用目标文件编译规则
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(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:
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版本
gui: directories $(GUI_TARGET)
# 安装规则(可选)
install: all
Write-Host "Installing executables..."
Copy-Item -Path "$(GUI_TARGET)" -Destination "C:\Program Files\Gobang\" -Force
# 运行GUI版本
run-gui: $(GUI_TARGET)
& ".\$(GUI_TARGET)"
# 帮助信息
help:
@echo Available targets:
@echo all - Build GUI version
@echo gui - Build GUI version
@echo clean - Remove all object files and executables
@echo run-gui - Build and run GUI version
@echo install - Install executables to system directory
@echo help - Show this help message
# 声明伪目标
.PHONY: all clean gui install run-gui help directories
+96 -238
View File
@@ -1,299 +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-v7.0-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)
> 🎯 **最新版本 v7.0** - 代码架构重构更新,实现结构体定义集中化、配置参数统一管理、代码模块化优化等核心改进 > 🎯 **最新版本 v9.0** - 全面集成 ENet 网络联机功能,重构 GUI 代码架构,纯图形化交互体验。
## 📋 大版本更新 ## 📋 大版本更新
### v7.0 (2025-07-20) - 代码架构重构更新 ### v9.0 (2026-03-17) - 局域网联机与 GUI 架构重构
- 🏗️ **结构体定义集中化** - 所有数据结构统一管理在type.h中
- ⚙️ **配置参数统一管理** - 所有配置宏定义集中在config.h中
- 🔧 **代码模块化优化** - 消除重复定义,提高代码可维护性
- 📋 **菜单选项优化** - 退出选项调整为"0. 退出游戏"
- 🎯 **类型系统完善** - 独立的type.h文件管理所有数据类型
- 🌐 **网络配置重构** - 网络相关宏定义统一到config.h
- 📊 **全局变量管理** - 优化全局变量声明和定义结构
- 🔄 **头文件依赖优化** - 改进模块间依赖关系和包含结构
- 🌐 **局域网对战** - 引入 ENet 库,支持稳定、无粘包的局域网多人对战(创建房间/加入房间)。
- 🎨 **GUI 深度重构** - 拆分臃肿的 GUI 代码,模块化为 `gui_core`, `gui_game`, `gui_menu`, `gui_draw`, `gui_replay`,大幅提升可维护性。
- 📦 **精简安装包** - 优化 Inno Setup 打包脚本,实现极简核心依赖打包。
- **全面摒弃控制台** - 专注于基于 IUP 的原生图形化交互体验。
---
## 目录 ## 目录
- [C语言五子棋人机对战AI](#c语言五子棋人机对战ai)
- [C语言五子棋系统](#c语言五子棋系统)
- [📋 大版本更新](#-大版本更新) - [📋 大版本更新](#-大版本更新)
- [v7.0 (2025-07-20) - 代码架构重构更新](#v70-2025-07-20---代码架构重构更新) - [v9.0 (2026-03-17) - 局域网联机与 GUI 架构重构](#v90-2026-03-17---局域网联机与-gui-架构重构)
- [目录](#目录) - [目录](#目录)
- [项目简介](#项目简介) - [项目简介](#项目简介)
- [功能特性](#功能特性) - [功能特性](#功能特性)
- [🎮 游戏模式](#-游戏模式) - [🎮 游戏模式](#-游戏模式)
- [⚙️ 游戏设置](#-游戏设置) - [⚙️ 核心功能](#-核心功能)
- [🎯 游戏功能](#-游戏功能)
- [💻 用户体验](#-用户体验)
- [🔧 技术特性](#-技术特性)
- [快速开始](#快速开始) - [快速开始](#快速开始)
- [编译项目](#编译项目) - [编译项目](#编译项目)
- [运行游戏](#运行游戏) - [打包安装程序](#打包安装程序)
- [游戏玩法](#游戏玩法) - [游戏玩法](#游戏玩法)
- [🚀 快速开始](#-快速开始) - [技术架构](#技术架构)
- [🎯 对局操作](#-对局操作) - [AI 算法](#ai-算法)
- [⚙️ 配置管理](#-配置管理) - [网络通信](#网络通信)
- [📊 复盘功能](#-复盘功能) - [图形界面](#图形界面)
- [🌐 网络对战功能](#-网络对战功能)
- [环境要求](#环境要求)
- [常见问题](#常见问题)
- [权限问题](#权限问题)
- [乱码显示问题](#乱码显示问题)
- [AI 设计实现](#ai-设计实现)
- [核心算法](#核心算法)
- [棋局评估函数](#棋局评估函数)
- [项目结构](#项目结构) - [项目结构](#项目结构)
- [📁 核心模块](#-核心模块)
- [🎮 功能模块](#-功能模块)
- [📄 配置和文档](#-配置和文档)
- [🔧 开发工具](#-开发工具)
- [许可证](#许可证) - [许可证](#许可证)
- [欢迎贡献](#欢迎贡献)
- [未来计划](#未来计划) ---
- [✅ 已完成功能](#-已完成功能)
- [🚀 开发路线图](#-开发路线图)
- [📱 用户体验提升](#-用户体验提升)
- [🌐 网络功能](#-网络功能)
- [🧠 AI增强](#-ai增强)
- [🔧 技术优化](#-技术优化)
## 项目简介 ## 项目简介
这是一个使用C语言实现的现代化五子棋对战系统,支持人机对战、双人对战和网络对战三种模式。系统基于 Alpha-Beta 剪枝优化的 Minimax 算法,具备完整的配置管理、复盘分析、智能评分和网络通信功能。
这是一个使用纯 C 语言编写的现代化五子棋系统。采用轻量级的 IUP 库构建原生风格的图形化用户界面。系统不仅支持基于 Minimax 算法(带 Alpha-Beta 剪枝)的高级人机对战,还完美支持基于 ENet 的局域网多人实时联机对弈。
## 功能特性 ## 功能特性
### 🎮 游戏模式 ### 🎮 游戏模式
- **人机对战模式** - 与智能AI进行对弈
- **双人对战模式** - 支持本地双人游戏
- **复盘模式** - 回顾和分析历史对局
### ⚙️ 游戏设置 - **人机对战 (PvE)** - 挑战 1-5 级难度的智能 AI。
- **自定义棋盘尺寸** - 支持5x5至25x25可调节棋盘 - **局域网联机 (Network)** - 建立主机或作为客机加入,与朋友在局域网内实时对战。
- **多级AI难度** - 1-5级智能难度可选 - **复盘模式 (Replay)** - 载入自动保存的对局记录(CSV),逐步回放并分析对局。
- **配置管理系统** - 持久化保存游戏设置
- **禁手规则支持** - 可选启用五子棋标准禁手规则
- **回合计时器** - 可设置每回合思考时间限制
### 🎯 游戏功能 ### ⚙️ 核心功能
- **实时对局控制** - 悔棋、认输、保存等操作
- **自动游戏记录** - 完整保存对局过程到CSV文件
- **智能评分系统** - 对每步棋进行专业评分和分析
- **完整复盘功能** - 逐步回放对局并显示评分
- **MVP评选系统** - 自动评选对局最佳表现者
### 💻 用户体验 - **实时对局控制** - 支持悔棋(PvE)、断线重连检测、胜负判定。
- **现代化UI界面** - 清晰直观的终端用户界面 - **自动游戏记录** - 每局游戏结束后自动保存至 `bin/records/` 目录。
- **完备输入验证** - 确保所有用户输入的有效性和安全性 - **模块化构建** - 提供高度配置化的 Makefile,一键源码编译包含 ENet 和主程序的二进制文件。
- **智能错误提示** - 详细的错误信息和操作指导
- **跨平台兼容** - 支持Windows系统,预留跨平台扩展
### 🔧 技术特性 ---
- **模块化架构** - 清晰的代码结构,便于维护和扩展
- **结构体定义集中化** - 所有数据结构统一在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
``` ```
**注意:** Windows系统需要添加 `-lws2_32` 链接库以支持网络功能 ### 打包安装程序
### 运行游戏 如果你需要将游戏打包成 Windows 安装程序,项目提供了 Inno Setup 脚本。
```bash 确保你已安装 [Inno Setup 6](https://jrsoftware.org/isinfo.php),然后运行:
.\gobang.exe
```powershell
& "D:\Program Files (x86)\Inno Setup 6\iscc.exe" installer\installer.iss
``` ```
生成的安装包 `Gobang_Inno_Setup.exe` 将存放在 `installer\dist\` 目录下。
---
## 游戏玩法 ## 游戏玩法
### 🚀 快速开始 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)
├── src/ # 核心源代码
### 🎮 功能模块 │ ├── main.c # 程序入口
- **`ui.c/h`** - 用户界面模块,负责所有显示和交互 │ ├── gobang.c # 五子棋核心规则与逻辑
- **`record.c/h`** - 游戏记录系统 (保存、加载、复盘、评分) │ ├── ai.c # 智能 AI 算法
- **`init_board.c/h`** - 棋盘初始化和游戏设置 │ ├── network.c # ENet 网络通信封装
- **`config.c/h`** - 配置管理系统 (参数设置、文件读写) │ ├── record.c # 棋谱记录与解析
- **`globals.c/h`** - 全局变量统一管理模块 │ ├── gui_core.c # GUI 初始化与核心循环
- **`network.c/h`** - 网络功能模块 (为未来网络对战预留) │ ├── gui_game.c # 游戏主界面与交互逻辑
│ ├── gui_menu.c # 游戏主菜单界面
### 📄 配置和文档 │ ├── gui_draw.c # 棋盘与棋子渲染
- **`gobang_config.ini`** - 游戏配置文件 (自动生成和保存) │ └── gui_replay.c # 复盘模式交互逻辑
- **`records/`** - 对局记录目录 (CSV格式存储) ├── installer/ # Inno Setup 安装包打包脚本及输出
- **`type.h`** - 数据结构和类型定义集中文件 ├── Makefile # 自动化构建脚本
- **`MD/README.md`** - 项目说明文档 └── README.md # 项目说明文档
- **`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] **模块化架构设计** - 完成代码重构,实现清晰的模块分离
- [x] **全局变量统一管理** - 所有全局变量集中在globals模块中管理
- [x] **宏定义优化** - 消除重复定义,统一管理所有宏定义
- [x] **配置管理系统** - 实现INI配置文件的自动加载和保存
- [x] **完整复盘功能** - 支持对局记录、回放和专业评分分析
- [x] **用户界面优化** - 实现现代化的终端UI界面
- [x] **智能评分系统** - 完成每步棋的评分和MVP评选功能
- [x] **禁手规则支持** - 添加标准五子棋禁手规则选项
- [x] **网络模块预留** - 为未来网络对战功能预留完整接口
### 🚀 开发路线图
#### 📱 用户体验提升
- [ ] **图形用户界面 (GUI)**:使用 `SDL2``Qt` 开发现代化图形界面
- [ ] **主题系统**:支持多种UI主题和棋盘样式
- [ ] **音效系统**:添加落子音效和背景音乐
#### 🌐 网络功能
- [ ] **在线对战模式**:实现网络多人对战功能
- [ ] **排行榜系统**:在线玩家等级和排名系统
- [ ] **观战功能**:支持观看其他玩家对局
#### 🧠 AI增强
- [ ] **开局库系统**:集成专业开局棋谱数据库
- [ ] **神经网络AI**:基于深度学习的高级AI对手
- [ ] **AI训练模式**:允许AI通过对局学习和改进
#### 🔧 技术优化
- [ ] **跨平台支持**:完整支持Linux和macOS系统
- [ ] **性能优化**:多线程搜索和内存优化
- [ ] **数据库支持**:使用SQLite存储对局历史和统计
-158
View File
@@ -1,158 +0,0 @@
五子棋对战系统 - 代码统计报告
========================================
项目名称:五子棋多模式对战系统
统计时间:2025年7月20日
项目版本:v7.0
开发语言:C语言
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行
【头文件 (.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行
========================================
📈 总计统计
========================================
总代码行数:4,398行
文件类型分布:
• C源文件:3,527行 (80.2%)
• 头文件:871行 (19.8%)
模块代码分布:
• 游戏模式模块:917行 (20.9%)
• AI智能模块:589行 (13.4%)
• 记录系统模块: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双平台兼容
【技术亮点】
• 完整的网络对战功能实现
• 智能AI算法与评估系统
• 灵活的配置管理系统
• 详细的游戏记录与复盘功能
• 规范的禁手规则实现
• 实时计时器系统
• 全局变量统一管理
• 跨平台网络通信支持
• 代码架构模块化重构(v7.0新增)
• 配置参数集中化管理(v7.0新增)
• 类型定义标准化(v7.0新增)
【总体评价】
这是一个非常优秀的C语言项目,代码量适中但功能完整,
注释详尽,体现了良好的编程习惯和专业素养!
项目从单一的五子棋游戏发展为支持多种对战模式的完整系统,
包括人机对战、双人对战和网络对战,功能丰富,架构清晰,
是C语言项目开发的优秀范例。
网络对战功能的加入使得项目具备了现代化游戏的特征,
支持实时在线对战,为用户提供了更丰富的游戏体验。
v7.0版本的代码架构重构是项目发展的重要里程碑,
通过配置统一管理、全局变量规范化、类型定义标准化等措施,
大幅提升了代码的可维护性和扩展性,为后续功能开发
奠定了坚实的架构基础。
========================================
📋 项目文件结构
========================================
核心模块:
• main.c/gobang.c - 主程序和核心游戏逻辑
• game_mode.c/h - 游戏模式管理(人机/双人/网络)
• ai.c/h - AI智能算法实现
• 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 - 游戏配置文件
文档目录:
• MD/ - 项目文档目录
• records/ - 游戏记录存储目录
开发环境:
• .vscode/ - VS Code配置
• .idea/ - IntelliJ IDEA配置
========================================
-87
View File
@@ -1,87 +0,0 @@
/**
* @file 五子棋对战系统
* @brief C语言五子棋多模式对战系统
* @details 支持人机对战、双人对战、网络对战的完整五子棋游戏系统
* @author 刘航宇(3364451258@qq.com、15236416560@163.com、lhy3364451258@outlook.com)
* @date 2025-07-20
* @version 7.0
* @note
* 1. 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报告和功能建议欢迎通过邮件反馈
* - 💡 网络对战相关问题请详细描述网络环境和连接状态
*/
Binary file not shown.
BIN
View File
Binary file not shown.
-331
View File
@@ -1,331 +0,0 @@
#include "config.h"
#include "ui.h"
#include "game_mode.h"
#include "globals.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @brief 加载游戏配置
*/
void load_game_config()
{
FILE *file = fopen(CONFIG_FILE, "r");
if (file == NULL)
{
// 配置文件不存在,使用默认配置
printf("配置文件不存在,使用默认配置\n");
return;
}
char line[256];
while (fgets(line, sizeof(line), file))
{
// 去除换行符
line[strcspn(line, "\n")] = 0;
// 解析配置项
if (strncmp(line, "BOARD_SIZE=", 11) == 0)
{
int size = atoi(line + 11);
if (size >= MIN_BOARD_SIZE && size <= MAX_BOARD_SIZE)
{
BOARD_SIZE = size;
}
}
else if (strncmp(line, "USE_FORBIDDEN_MOVES=", 20) == 0)
{
use_forbidden_moves = (atoi(line + 20) != 0);
}
else if (strncmp(line, "USE_TIMER=", 10) == 0)
{
use_timer = atoi(line + 10);
}
else if (strncmp(line, "TIME_LIMIT=", 11) == 0)
{
time_limit = atoi(line + 11);
}
else if (strncmp(line, "NETWORK_PORT=", 13) == 0)
{
int port = atoi(line + 13);
if (port >= MIN_NETWORK_PORT && port <= MAX_NETWORK_PORT)
{
network_port = port;
}
}
else if (strncmp(line, "NETWORK_TIMEOUT=", 16) == 0)
{
int timeout = atoi(line + 16);
if (timeout > 0)
{
network_timeout = timeout;
}
}
else if (strncmp(line, "AI_DIFFICULTY=", 14) == 0)
{
int difficulty = atoi(line + 14);
if (difficulty >= 1 && difficulty <= 5)
{
// 根据难度设置AI搜索深度
// 这里可以添加AI难度相关的配置
}
}
}
fclose(file);
printf("配置加载完成\n");
}
/**
* @brief 保存游戏配置
*/
void save_game_config()
{
FILE *file = fopen(CONFIG_FILE, "w");
if (file == NULL)
{
printf("无法保存配置文件\n");
return;
}
fprintf(file, "# 五子棋游戏配置文件\n");
fprintf(file, "# 棋盘大小 (范围: %d-%d)\n", MIN_BOARD_SIZE, MAX_BOARD_SIZE);
fprintf(file, "BOARD_SIZE=%d\n", BOARD_SIZE);
fprintf(file, "\n# 禁手规则 (0=关闭, 1=开启)\n");
fprintf(file, "USE_FORBIDDEN_MOVES=%d\n", use_forbidden_moves ? 1 : 0);
fprintf(file, "\n# 计时器 (0=关闭, 1=开启)\n");
fprintf(file, "USE_TIMER=%d\n", use_timer);
fprintf(file, "\n# 时间限制 (分钟)\n");
fprintf(file, "TIME_LIMIT=%d\n", time_limit);
fprintf(file, "\n# 网络端口 (范围: %d-%d)\n", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
fprintf(file, "NETWORK_PORT=%d\n", network_port);
fprintf(file, "\n# 网络超时时间 (毫秒)\n");
fprintf(file, "NETWORK_TIMEOUT=%d\n", network_timeout);
fclose(file);
printf("配置保存完成\n");
}
/**
* @brief 重置为默认配置
*/
void reset_to_default_config()
{
BOARD_SIZE = DEFAULT_BOARD_SIZE;
use_forbidden_moves = DEFAULT_USE_FORBIDDEN_MOVES;
use_timer = DEFAULT_USE_TIMER;
time_limit = DEFAULT_TIME_LIMIT;
network_port = DEFAULT_NETWORK_PORT;
network_timeout = NETWORK_TIMEOUT_MS;
printf("已重置为默认配置\n");
}
/**
* @brief 显示当前配置
*/
void display_current_config()
{
printf("\n===== 当前游戏配置 =====\n");
printf("棋盘大小: %d x %d\n", BOARD_SIZE, BOARD_SIZE);
printf("禁手规则: %s\n", use_forbidden_moves ? "开启" : "关闭");
printf("计时器: %s\n", use_timer ? "开启" : "关闭");
if (use_timer)
{
printf("时间限制: %d 分钟\n", time_limit / 60);
}
printf("网络端口: %d\n", network_port);
printf("网络超时: %d 毫秒\n", network_timeout);
printf("=====================\n");
}
/**
* @brief 配置棋盘大小
*/
void config_board_size()
{
printf("\n当前棋盘大小: %d x %d\n", BOARD_SIZE, BOARD_SIZE);
printf("请输入新的棋盘大小 (%d-%d): ", MIN_BOARD_SIZE, MAX_BOARD_SIZE);
int new_size;
if (scanf("%d", &new_size) == 1)
{
if (new_size >= MIN_BOARD_SIZE && new_size <= MAX_BOARD_SIZE)
{
BOARD_SIZE = new_size;
printf("棋盘大小已设置为: %d x %d\n", BOARD_SIZE, BOARD_SIZE);
}
else
{
printf("无效的棋盘大小!\n");
}
}
else
{
printf("输入格式错误!\n");
// 清除输入缓冲区
while (getchar() != '\n');
}
}
/**
* @brief 配置禁手规则
*/
void config_forbidden_moves()
{
printf("\n当前禁手规则: %s\n", use_forbidden_moves ? "开启" : "关闭");
printf("是否启用禁手规则?(1=开启, 0=关闭): ");
int choice;
if (scanf("%d", &choice) == 1)
{
use_forbidden_moves = (choice != 0);
printf("禁手规则已%s\n", use_forbidden_moves ? "开启" : "关闭");
}
else
{
printf("输入格式错误!\n");
while (getchar() != '\n');
}
}
/**
* @brief 配置计时器
*/
void config_timer()
{
printf("\n当前计时器: %s\n", use_timer ? "开启" : "关闭");
printf("是否启用计时器?(1=开启, 0=关闭): ");
int choice;
if (scanf("%d", &choice) == 1)
{
use_timer = choice;
if (use_timer)
{
printf("请输入时间限制(分钟): ");
int new_limit;
if (scanf("%d", &new_limit) == 1 && new_limit > 0)
{
time_limit = new_limit * 60; // 转换为秒数存储
printf("计时器已开启,时间限制: %d 分钟\n", time_limit / 60);
}
else
{
printf("无效的时间限制!\n");
while (getchar() != '\n');
}
}
else
{
printf("计时器已关闭\n");
}
}
else
{
printf("输入格式错误!\n");
while (getchar() != '\n');
}
}
/**
* @brief 配置网络参数
*/
void config_network()
{
printf("\n===== 网络配置 =====\n");
printf("当前网络端口: %d\n", network_port);
printf("当前网络超时: %d 毫秒\n", network_timeout);
printf("\n请输入新的网络端口 (%d-%d): ", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
int new_port;
if (scanf("%d", &new_port) == 1)
{
if (new_port >= MIN_NETWORK_PORT && new_port <= MAX_NETWORK_PORT)
{
network_port = new_port;
printf("网络端口已设置为: %d\n", network_port);
}
else
{
printf("无效的端口号!端口范围: %d-%d\n", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
}
}
else
{
printf("输入格式错误!\n");
while (getchar() != '\n');
}
printf("\n请输入网络超时时间(毫秒, 建议1000-10000): ");
int new_timeout;
if (scanf("%d", &new_timeout) == 1)
{
if (new_timeout > 0)
{
network_timeout = new_timeout;
printf("网络超时已设置为: %d 毫秒\n", network_timeout);
}
else
{
printf("无效的超时时间!\n");
}
}
else
{
printf("输入格式错误!\n");
while (getchar() != '\n');
}
}
/**
* @brief 配置管理主菜单
*/
void config_management_menu()
{
int choice;
while (1)
{
clear_screen();
display_settings_menu();
display_current_config();
printf("请选择操作: ");
if (scanf("%d", &choice) != 1)
{
printf("输入格式错误!\n");
while (getchar() != '\n');
pause_for_input("按任意键继续...");
continue;
}
switch (choice)
{
case 1:
config_board_size();
break;
case 2:
config_forbidden_moves();
break;
case 3:
config_timer();
break;
case 4:
config_network();
break;
case 5:
printf("AI难度设置功能开发中...\n");
break;
case 6:
save_game_config();
return;
default:
printf("无效的选择!\n");
break;
}
pause_for_input("按任意键继续...");
}
}
-917
View File
@@ -1,917 +0,0 @@
#include "game_mode.h"
#include "init_board.h"
#include "gobang.h"
#include "ai.h"
#include "record.h"
#include "config.h"
#include "network.h"
#include "ui.h"
#include "globals.h"
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <ctype.h>
// 全局变量现在在globals.c中定义
#ifdef _WIN32
#include <windows.h>
#include <direct.h>
#include <conio.h>
#endif
/**
* @brief 从用户获取整数输入
*
* @param prompt 提示信息
* @param min 最小值
* @param max 最大值
* @return int 用户输入的整数
*/
int get_integer_input(const char *prompt, int min, int max)
{
int value;
int result;
char ch;
while (1)
{
printf("%s", prompt);
result = scanf("%d", &value);
if (result == 1 && value >= min && value <= max)
{
// 清除输入缓冲区中剩余的字符
while ((ch = getchar()) != '\n' && ch != EOF)
;
return value;
}
else
{
// 清除无效输入
while ((ch = getchar()) != '\n' && ch != EOF)
;
printf("输入无效,请输入一个介于 %d 和 %d 之间的整数。\n", min, max);
}
}
}
/**
* @brief 处理玩家回合
*
* @param current_player
* @return true
* @return false
*/
bool parse_player_input(int *x, int *y)
{
char input[10];
while (1)
{
if (_kbhit())
{
scanf("%s", input);
break;
}
Sleep(100); // 短暂延迟以防止CPU占用过高
}
if (sscanf(input, "%d", x) == 1)
{
// 成功解析第一个数字,现在解析第二个
if (scanf("%d", y) != 1)
{
// 如果第二个数字不可用,则检查特殊命令
if (*x == INPUT_UNDO)
{
int steps_to_undo;
steps_to_undo = get_integer_input("请输入要悔棋的步数(双方各退步数相同): ", 1, step_count / 2);
if (return_move(steps_to_undo * 2))
{
printf("成功悔棋,双方各退 %d 步!\n", steps_to_undo);
print_board();
}
else
{
printf("无法悔棋!\n");
}
return 0; // 特殊命令已处理
}
else if (*x == INPUT_SAVE)
{
// ... 处理保存 ...
return false; // 特殊命令
}
else if (*x == INPUT_EXIT)
{
// ... 处理退出 ...
return false; // 特殊命令
}
printf("无效输入,请输入两个数字坐标。\n");
while (getchar() != '\n')
;
return 0; // 无效输入
}
}
else
{
// sscanf失败,检查特殊命令
if (input[0] == 'r' || input[0] == 'R')
{
int steps_to_undo;
steps_to_undo = get_integer_input("请输入要悔棋的步数(双方各退步数相同): ", 1, step_count / 2);
if (return_move(steps_to_undo * 2))
{
printf("成功悔棋,双方各退 %d 步!\n", steps_to_undo);
print_board();
}
else
{
printf("无法悔棋!\n");
}
return false; // 特殊命令
}
else if (input[0] == 's' || input[0] == 'S')
{
*x = INPUT_SURRENDER;
int confirm = get_integer_input("确认认输?(1:是/0:否): ", 0, 1);
if (confirm)
{
printf("玩家选择认输!\n");
return 1; // 正常回合完成 // 返回认输命令
}
else
{
printf("取消认输!\n");
return false; // 取消认输
}
}
printf("无效输入,请输入数字坐标、'r'悔棋或's'认输。\n");
return 0; // 无效输入
}
return 1; // 有效坐标
}
/**
* @brief 解析网络对战模式下的玩家输入
* @param x 行坐标指针
* @param y 列坐标指针
* @return true 有效坐标输入
* @return false 特殊命令或无效输入
*/
bool parse_network_player_input(int *x, int *y)
{
char input[10];
while (1)
{
if (_kbhit())
{
scanf("%s", input);
break;
}
Sleep(100); // 短暂延迟以防止CPU占用过高
}
if (sscanf(input, "%d", x) == 1)
{
// 成功解析第一个数字,现在解析第二个
if (scanf("%d", y) != 1)
{
printf("无效输入,请输入两个数字坐标。\n");
while (getchar() != '\n')
;
return false; // 无效输入
}
}
else
{
// sscanf失败,检查特殊命令
if (input[0] == 'r' || input[0] == 'R')
{
int steps_to_undo;
steps_to_undo = get_integer_input("请输入要悔棋的步数(双方各退步数相同): ", 1, step_count / 2);
printf("发送悔棋请求给对方...\n");
if (send_undo_request(steps_to_undo))
{
printf("悔棋请求已发送,等待对方回应...\n");
// 等待对方回应
NetworkMessage msg;
time_t start_time = time(NULL);
while (difftime(time(NULL), start_time) < 30) // 30秒超时
{
if (receive_network_message(&msg, 1000))
{
if (msg.type == MSG_UNDO_RESPONSE && msg.x == steps_to_undo)
{
if (msg.y == 1) // 对方同意
{
if (return_move(steps_to_undo * 2))
{
printf("对方同意悔棋,双方各退 %d 步!\n", steps_to_undo);
print_board();
return 2; // 悔棋成功,需要重新开始回合
}
else
{
printf("悔棋失败!\n");
return 0; // 悔棋失败,继续当前回合
}
}
else // 对方拒绝
{
printf("对方拒绝了悔棋请求。\n");
return 0; // 悔棋被拒绝,继续当前回合
}
}
}
if (!is_network_connected())
{
printf("网络连接断开\n");
return 0;
}
}
printf("悔棋请求超时,对方未回应。\n");
}
else
{
printf("发送悔棋请求失败!\n");
}
return 0; // 特殊命令已处理
}
else if (input[0] == 's' || input[0] == 'S')
{
*x = INPUT_SURRENDER;
int confirm = get_integer_input("确认认输?(1:是/0:否): ", 0, 1);
if (confirm)
{
printf("你选择认输!\n");
*x = INPUT_SURRENDER;
return -1; // 返回认输命令
}
else
{
printf("取消认输!\n");
return 0; // 取消认输
}
}
printf("无效输入,请输入数字坐标、'r'悔棋或's'认输。\n");
return false; // 无效输入
}
return true; // 有效坐标
}
/**
* @brief 处理玩家回合
* @param current_player 当前玩家
* @return true
*/
bool handle_player_turn(int current_player)
{
int x, y;
time_t start_time, end_time;
if (use_timer)
{
time(&start_time);
}
while (1)
{
printf("\n玩家%d, 请输入落子坐标(行 列,1~%d),或输入R/r悔棋,S/s认输:", current_player, BOARD_SIZE);
bool input_received = false;
while (!input_received)
{
if (use_timer)
{
time(&end_time);
if (difftime(end_time, start_time) > time_limit)
{
printf("\n玩家%d超时, 对方获胜!\n", current_player);
return false; // Timeout
}
}
if (parse_player_input(&x, &y))
{
if (x == INPUT_SURRENDER)
{
printf("\n玩家%d选择认输,对方获胜!\n", current_player);
return false; // 游戏结束,认输
}
input_received = true;
}
else
{
// 已处理特殊命令或无效输入,继续循环
return true;
}
}
x--;
y--;
if (player_move(x, y, current_player))
{
break; // 成功落子,跳出循环
}
else
{
printf("坐标无效!请重新输入。\n");
// 继续循环,重新输入坐标
}
}
print_board();
if (check_win(x, y, current_player))
{
printf("\n玩家%d获胜!\n", current_player);
return false; // 游戏结束
}
return true; // 成功落子
}
/**
* @brief 运行AI游戏
* @note 从文件中加载历史记录并进行复盘
* @param AI_DEPTH AI的搜索深度
*/
void run_ai_game()
{
// 重置评分计算标志,确保每局游戏都会重新计算评分
scores_calculated = 0;
// AI对战模式
int AI_DEPTH = 3;
AI_DEPTH = get_integer_input("请选择AI难度(1~5), 数字越大越强,注意数字越大AI思考时间越长!):", 1, 5);
/**
* @brief AI的防守系数,系数越大越倾向于防守
* @note 1~1.2
* 2~1.3
* 3~1.4
* 4~1.5
* 5~1.6
*/
defense_coefficient = 1.2 + (AI_DEPTH - 1) * 0.1;
empty_board();
int current_player = determine_first_player(PLAYER, AI);
print_board();
while (1)
{
if (current_player == PLAYER)
{
int old_step_count = step_count;
if (!handle_player_turn(current_player))
{
break; // 游戏结束或超时
}
if (step_count > old_step_count)
{
// 检查玩家是否获胜
Step last_step = steps[step_count - 1];
if (check_win(last_step.x, last_step.y, PLAYER))
{
printf("\n玩家获胜!\n");
break;
}
current_player = AI;
}
}
else
{
printf("\nAI思考中...\n");
time_t start_time, end_time;
if (use_timer)
{
time(&start_time);
}
ai_move(AI_DEPTH);
if (use_timer)
{
time(&end_time);
if (difftime(end_time, start_time) > time_limit)
{
printf("\nAI超时, 玩家获胜!\n");
break;
}
}
print_board();
Step last_step = steps[step_count - 1];
if (check_win(last_step.x, last_step.y, AI))
{
printf("\nAI获胜!\n");
break;
}
current_player = PLAYER;
}
if (step_count == BOARD_SIZE * BOARD_SIZE)
{
printf("\n平局!\n");
break;
}
}
printf("===== 游戏结束 =====\n");
review_process(GAME_MODE_AI); // AI对战模式
handle_save_record(GAME_MODE_AI); // AI对战模式
}
/**
* @brief 运行双人对战模式
* @note 从文件中加载历史记录并进行复盘
*/
void run_pvp_game()
{
// 重置评分计算标志,确保每局游戏都会重新计算评分
scores_calculated = 0;
// 双人对战模式
empty_board();
int current_player = determine_first_player(PLAYER1, PLAYER2);
print_board();
while (1)
{
int old_step_count = step_count;
if (!handle_player_turn(current_player))
{
break; // 游戏结束或超时
}
if (step_count == BOARD_SIZE * BOARD_SIZE)
{
printf("\n平局!\n");
break;
}
if (step_count > old_step_count)
{
current_player = (current_player == PLAYER1) ? PLAYER2 : PLAYER1;
}
}
printf("===== 游戏结束 =====\n");
review_process(GAME_MODE_PVP); // 双人对战模式
handle_save_record(GAME_MODE_PVP); // 双人对战模式
}
/**
* @brief 运行复盘模式
* @note 从文件中加载历史记录并进行复盘
*/
void run_review_mode()
{
char filename[100];
char record_files[100][100];
int file_count = 0;
#ifdef _WIN32
WIN32_FIND_DATA ffd;
HANDLE hFind = FindFirstFile("records\\*", &ffd);
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
strcpy(record_files[file_count++], ffd.cFileName);
}
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
}
#endif
if (file_count > 0)
{
printf("发现以下复盘文件:\n");
for (int i = 0; i < file_count; i++)
{
printf("%d. %s\n", i + 1, record_files[i]);
}
char prompt[150];
sprintf(prompt, "请输入复盘文件编号(1-%d),或输入0以手动输入文件名: ", file_count);
int choice = get_integer_input(prompt, 0, file_count);
if (choice > 0)
{
strcpy(filename, record_files[choice - 1]);
}
else
{
printf("请输入完整文件名: ");
scanf("%s", filename);
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
int possible_choice = atoi(filename);
if (possible_choice > 0 && possible_choice <= file_count)
{
strcpy(filename, record_files[possible_choice - 1]);
}
}
}
else
{
printf("未找到任何复盘文件,请输入复盘文件地址: ");
scanf("%s", filename);
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
}
int game_mode = load_game_from_file(filename);
if (game_mode != 0)
{
if (game_mode == 1)
{
printf("加载AI对战模式复盘文件成功!\n");
}
else if (game_mode == 2)
{
printf("加载双人对战模式复盘文件成功!\n");
}
review_process(game_mode);
}
else
{
printf("加载复盘文件失败!可能是旧版本文件格式或文件损坏\n");
}
}
/**
* @brief 网络对战模式
*/
void run_network_game()
{
// 重置评分计算标志
scores_calculated = 0;
// 初始化网络模块
if (!init_network())
{
printf("网络初始化失败!\n");
pause_for_input("按任意键返回主菜单...");
return;
}
printf("=== 网络对战模式 ===\n");
printf("1. 创建房间(作为主机)\n");
printf("2. 加入房间(连接到主机)\n");
int choice = get_integer_input("请选择模式(1-2): ", 1, 2);
bool connection_success = false;
if (choice == 1)
{
// 服务器模式
int port = get_integer_input("请输入监听端口(默认8888): ", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
if (port == 0) port = network_port;
printf("\n正在创建房间...\n");
connection_success = create_server(port);
}
else
{
// 客户端模式
char ip[MAX_IP_LENGTH];
// 循环直到输入有效的IP地址或用户选择退出
while (1)
{
printf("请输入服务器IP地址 (输入'exit'退出): ");
if (scanf("%s", ip) != 1)
{
printf("输入错误,请重新输入。\n");
// 清除输入缓冲区
while (getchar() != '\n');
continue;
}
// 检查是否要退出
if (strcmp(ip, "exit") == 0 || strcmp(ip, "EXIT") == 0)
{
printf("取消连接,返回主菜单。\n");
cleanup_network();
pause_for_input("按任意键返回主菜单...");
return;
}
// 简单的IP地址格式验证
if (strlen(ip) < 7 || strlen(ip) > 15)
{
printf("IP地址格式错误!请输入有效的IP地址(如:192.168.1.100\n");
continue;
}
// 检查IP地址是否包含有效字符
bool valid_ip = true;
for (int i = 0; i < strlen(ip); i++)
{
if (!(isdigit(ip[i]) || ip[i] == '.'))
{
valid_ip = false;
break;
}
}
if (!valid_ip)
{
printf("IP地址格式错误!只能包含数字和点号。\n");
continue;
}
// 检查点号数量
int dot_count = 0;
for (int i = 0; i < strlen(ip); i++)
{
if (ip[i] == '.') dot_count++;
}
if (dot_count != 3)
{
printf("IP地址格式错误!应包含3个点号(如:192.168.1.100\n");
continue;
}
printf("输入的IP地址: %s\n", ip);
int confirm = get_integer_input("确认连接到此IP?(1:是/0:否,重新输入): ", 0, 1);
if (confirm)
{
break; // 确认IP地址,跳出循环
}
// 如果选择否,继续循环重新输入
}
int port = get_integer_input("请输入服务器端口(默认8888): ", MIN_NETWORK_PORT, MAX_NETWORK_PORT);
if (port == 0) port = network_port;
printf("\n正在连接到服务器 %s:%d...\n", ip, port);
connection_success = connect_to_server(ip, port);
}
if (!connection_success)
{
printf("网络连接失败!\n");
cleanup_network();
pause_for_input("按任意键返回主菜单...");
return;
}
printf("\n网络连接成功!游戏即将开始...\n");
printf("你是玩家%d%s先手\n",
network_state.local_player_id,
network_state.local_player_id == PLAYER1 ? "" : "对方");
// 开始网络游戏
empty_board();
print_board();
if (network_game_loop())
{
printf("===== 游戏结束 =====\n");
review_process(GAME_MODE_NETWORK); // 网络对战模式的复盘
handle_save_record(GAME_MODE_NETWORK); // 保存为网络对战模式记录
}
else
{
printf("游戏因网络错误而结束\n");
}
// 清理网络连接
disconnect_network();
pause_for_input("按任意键返回主菜单...");
}
/**
* @brief 处理网络玩家回合
*/
bool handle_network_player_turn(int current_player, bool is_local_turn)
{
if (is_local_turn)
{
// 本地玩家回合
int x, y;
time_t start_time, end_time;
if (use_timer)
{
time(&start_time);
}
while (1)
{
printf("\n轮到你了,请输入落子坐标(行 列,1~%d),或输入R/r悔棋,S/s认输: ", BOARD_SIZE);
bool input_received = false;
while (!input_received)
{
if (use_timer)
{
time(&end_time);
if (difftime(end_time, start_time) > time_limit)
{
printf("\n你超时了,对方获胜!\n");
send_surrender(); // 发送认输消息
return 0; // 游戏结束
}
}
int parse_result = parse_network_player_input(&x, &y);
if (parse_result == 1) // 有效坐标输入
{
input_received = true;
}
else if (parse_result == -1) // 认输命令
{
printf("\n你选择认输,对方获胜!\n");
send_surrender();
return 0; // 游戏结束
}
else if (parse_result == 2) // 悔棋成功
{
return 2; // 悔棋发生,需要重新开始回合
}
else // parse_result == 0, 特殊命令已处理或无效输入
{
// 继续等待输入
continue;
}
}
x--; y--; // 转换为0-based坐标
if (player_move(x, y, current_player))
{
break; // 成功落子,跳出循环
}
else
{
printf("坐标无效!请重新输入。\n");
// 继续循环,重新输入坐标
}
}
// 发送落子消息
if (!send_move(x, y, current_player))
{
printf("发送落子消息失败!\n");
return 0; // 游戏结束
}
print_board();
if (check_win(x, y, current_player))
{
printf("\n你获胜了!\n");
return 0; // 游戏结束
}
}
else
{
// 等待对方落子
printf("\n等待对方落子...\n");
NetworkMessage msg;
time_t start_time = time(NULL);
while (1)
{
if (receive_network_message(&msg, 1000))
{
// 1秒超时
if (msg.type == MSG_MOVE && msg.player_id == current_player)
{
// 收到落子消息
if (!player_move(msg.x, msg.y, current_player))
{
printf("收到无效的落子坐标!\n");
return 0; // 游戏结束
}
printf("对方落子: (%d, %d)\n", msg.x + 1, msg.y + 1);
print_board();
if (check_win(msg.x, msg.y, current_player))
{
printf("\n对方获胜!\n");
return 0; // 游戏结束
}
break;
}
else if (msg.type == MSG_SURRENDER)
{
printf("\n对方认输,你获胜了!\n");
return 0; // 游戏结束
}
else if (msg.type == MSG_DISCONNECT)
{
printf("\n对方已断开连接\n");
return 0; // 游戏结束
}
else if (msg.type == MSG_CHAT)
{
printf("[对方]: %s\n", msg.message);
}
else if (msg.type == MSG_UNDO_REQUEST)
{
int steps = msg.x;
printf("\n对方请求悔棋 %d 步,是否同意?(1:同意/0:拒绝): ", steps);
int response = get_integer_input("", 0, 1);
if (response && return_move(steps * 2))
{
printf("同意悔棋,双方各退 %d 步\n", steps);
send_undo_response(true, steps);
print_board();
// 悔棋后需要重新开始当前回合,不改变current_player
return 2; // 悔棋发生,需要重新开始回合
}
else
{
printf("拒绝悔棋\n");
send_undo_response(false, steps);
// 继续等待对方落子
}
}
}
// 检查超时
if (use_timer && difftime(time(NULL), start_time) > time_limit)
{
printf("\n对方超时,你获胜!\n");
return 0; // 游戏结束
}
// 检查网络连接
if (!is_network_connected())
{
printf("\n网络连接断开\n");
return 0; // 游戏结束
}
}
}
return 1; // 正常回合完成
}
/**
* @brief 网络游戏主循环
*/
bool network_game_loop()
{
int current_player = PLAYER1; // 总是从玩家1开始
while (1)
{
bool is_local_turn = (current_player == network_state.local_player_id);
int turn_result = handle_network_player_turn(current_player, is_local_turn);
if (turn_result == 0) // 游戏结束
{
return true;
}
else if (turn_result == 2) // 悔棋发生,重新开始当前回合
{
continue; // 不切换玩家,重新开始当前回合
}
// 检查平局
if (step_count == BOARD_SIZE * BOARD_SIZE)
{
printf("\n平局!\n");
return true;
}
// 切换玩家
current_player = (current_player == PLAYER1) ? PLAYER2 : PLAYER1;
// 检查网络连接
if (!is_network_connected())
{
printf("\n网络连接断开\n");
return false;
}
}
return true;
}
-93
View File
@@ -1,93 +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();
#endif // GAME_MODE_H
-37
View File
@@ -1,37 +0,0 @@
/**
* @file globals.c
* @author 刘航宇(3364451258@qq.com、15236416560@163.com、lhy3364451258@outlook.com)
* @brief 全局变量定义和初始化文件
* @version 6.0
* @date 2025-07-10
* @note 集中管理所有全局变量的定义和初始化,提高代码可维护性
*/
#include "globals.h"
#include "config.h"
// ==================== 游戏核心变量定义 ====================
int BOARD_SIZE = DEFAULT_BOARD_SIZE; // 实际使用的棋盘尺寸
int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE] = {0}; // 棋盘状态存储数组(默认棋盘全空为0)
Step steps[MAX_STEPS]; // 存储所有落子步骤的数组
const int direction[4][2] = {{1, 0}, {0, 1}, {1, 1}, {1, -1}}; // 四个方向:向下、向右、右下、左下
int step_count = 0; // 当前步数计数器
// ==================== 游戏配置变量定义 ====================
bool use_forbidden_moves = DEFAULT_USE_FORBIDDEN_MOVES; // 是否启用禁手规则
int use_timer = DEFAULT_USE_TIMER; // 是否启用计时器
int time_limit = DEFAULT_TIME_LIMIT; // 每回合的时间限制(秒)
int network_port = DEFAULT_NETWORK_PORT; // 网络端口
int network_timeout = NETWORK_TIMEOUT_MS; // 网络超时时间
// ==================== AI相关变量定义 ====================
double defense_coefficient = DEFAULT_DEFENSE_COEFFICIENT; // 防守系数
// ==================== 网络相关变量定义 ====================
NetworkGameState network_state = {0}; // 网络游戏状态
// ==================== 记录相关变量定义 ====================
int player1_final_score = 0; // 玩家1最终得分
int player2_final_score = 0; // 玩家2最终得分
int scores_calculated = 0; // 评分计算标志
char winner_info[50] = "平局或未完成"; // 存储胜负信息
-41
View File
@@ -1,41 +0,0 @@
/**
* @file globals.h
* @brief 全局变量声明头文件
* @note 集中管理所有全局变量的声明,提高代码可维护性
*/
#ifndef GLOBALS_H
#define GLOBALS_H
#include "type.h"
#include "gobang.h"
#include "network.h"
#include <stdbool.h>
// ==================== 游戏核心变量 ====================
extern int BOARD_SIZE; // 当前实际使用的棋盘尺寸
extern int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; // 棋盘状态存储数组
extern Step steps[MAX_STEPS]; // 存储所有落子步骤的数组
extern const int direction[4][2]; // 四个方向:向下、向右、右下、左下
extern int step_count; // 当前步数计数器
// ==================== 游戏配置变量 ====================
extern bool use_forbidden_moves; // 是否启用禁手规则的标志
extern int use_timer; // 是否启用计时器的标志
extern int time_limit; // 每回合的时间限制(秒,内部存储)
extern int network_port; // 网络端口
extern int network_timeout; // 网络超时时间
// ==================== AI相关变量 ====================
extern double defense_coefficient; // 防守系数
// ==================== 网络相关变量 ====================
extern NetworkGameState network_state; // 网络游戏状态
// ==================== 记录相关变量 ====================
extern int player1_final_score; // 玩家1最终得分
extern int player2_final_score; // 玩家2最终得分
extern int scores_calculated; // 评分计算标志
extern char winner_info[50]; // 存储胜负信息
#endif // GLOBALS_H
+3
View File
@@ -16,3 +16,6 @@ NETWORK_PORT=8888
# 网络超时时间 (毫秒) # 网络超时时间 (毫秒)
NETWORK_TIMEOUT=5000 NETWORK_TIMEOUT=5000
# AI难度 (1-5)
AI_DIFFICULTY=3
+1
View File
@@ -6,6 +6,7 @@
* 2. * 2.
* 3. * 3.
*/ */
#ifndef AI_H #ifndef AI_H
#define AI_H #define AI_H
+38 -54
View File
@@ -32,40 +32,38 @@
#define INPUT_SURRENDER -4 // 认输 #define INPUT_SURRENDER -4 // 认输
//---------- 游戏设置默认值 ----------// //---------- 游戏设置默认值 ----------//
#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搜索深度(从3提升到5 #define DEFAULT_AI_DEPTH 5 // 默认AI搜索深度
#define DEFAULT_DEFENSE_COEFFICIENT 1.5 // 默认防守系数(从1.2提升到1.5 #define DEFAULT_DEFENSE_COEFFICIENT 1.5 // 默认防守系数
//---------- 网络参数 ----------// //---------- 网络参数 ----------//
#define DEFAULT_NETWORK_PORT 8888 // 默认网络端口 #define DEFAULT_NETWORK_PORT 8888 // 默认网络端口
#define MIN_NETWORK_PORT 1024 // 最小网络端口 #define MIN_NETWORK_PORT 1024 // 最小网络端口
#define MAX_NETWORK_PORT 65535 // 最大网络端口 #define MAX_NETWORK_PORT 65535 // 最大网络端口
#define NETWORK_TIMEOUT_MS 5000 // 网络超时时间(毫秒) #define NETWORK_TIMEOUT_MS 5000 // 网络超时时间(毫秒)
#define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小 #define NETWORK_BUFFER_SIZE 1024 // 网络缓冲区大小
// 网络配置 // 网络配置
#define DEFAULT_PORT 8888 // 默认端口(与DEFAULT_NETWORK_PORT保持一致) #define MAX_IP_LENGTH 16 // 最大IP地址长度
#define BUFFER_SIZE 1024 // 缓冲区大小(与NETWORK_BUFFER_SIZE保持一致)
#define MAX_IP_LENGTH 16 // 最大IP地址长度
// 网络消息类型 // 网络消息类型
#define MSG_MOVE 1 // 落子消息 #define MSG_MOVE 1 // 落子消息
#define MSG_CHAT 2 // 聊天消息 #define MSG_CHAT 2 // 聊天消息
#define MSG_SURRENDER 3 // 认输消息 #define MSG_SURRENDER 3 // 认输消息
#define MSG_UNDO_REQUEST 4 // 悔棋请求 #define MSG_UNDO_REQUEST 4 // 悔棋请求
#define MSG_UNDO_RESPONSE 5 // 悔棋回应 #define MSG_UNDO_RESPONSE 5 // 悔棋回应
#define MSG_GAME_START 6 // 游戏开始 #define MSG_GAME_START 6 // 游戏开始
#define MSG_GAME_END 7 // 游戏结束 #define MSG_GAME_END 7 // 游戏结束
#define MSG_HEARTBEAT 8 // 心跳包 #define MSG_HEARTBEAT 8 // 心跳包
#define MSG_DISCONNECT 9 // 断线消息 #define MSG_DISCONNECT 9 // 断线消息
//---------- 评分参数 ----------// //---------- 评分参数 ----------//
// 棋型评分 - 用于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 // 死四
@@ -116,7 +114,23 @@
#define TIME_WEIGHT_FACTOR 0.5 // 时间权重因子 #define TIME_WEIGHT_FACTOR 0.5 // 时间权重因子
#define WIN_BONUS 2000 // 胜利奖励分数 #define WIN_BONUS 2000 // 胜利奖励分数
// 文件路径参数 //---------- GUI界面参数 ----------//
// 窗口和棋盘配置
#define WINDOW_WIDTH 1000
#define WINDOW_HEIGHT 800
#define BOARD_OFFSET_X 50
#define BOARD_OFFSET_Y 50
#define CELL_SIZE 30
#define STONE_RADIUS 12
// 颜色定义
#define GUI_COLOR_BACKGROUND {240, 217, 181, 255}
#define GUI_COLOR_BOARD_LINE {0, 0, 0, 255}
#define GUI_COLOR_BLACK_STONE {0, 0, 0, 255}
#define GUI_COLOR_WHITE_STONE {255, 255, 255, 255}
#define GUI_COLOR_STONE_BORDER {100, 100, 100, 255}
//---------- 文件路径参数 ----------//
#define RECORDS_DIR "records" // 记录文件目录 #define RECORDS_DIR "records" // 记录文件目录
#define CONFIG_FILE "gobang_config.ini" // 配置文件路径 #define CONFIG_FILE "gobang_config.ini" // 配置文件路径
#define MAX_PATH_LENGTH 256 // 最大路径长度 #define MAX_PATH_LENGTH 256 // 最大路径长度
@@ -137,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
+46
View File
@@ -0,0 +1,46 @@
/**
* @file globals.h
* @brief 全局变量声明头文件
* @note 集中管理所有全局变量的声明,提高代码可维护性
*/
#ifndef GLOBALS_H
#define GLOBALS_H
#include "type.h"
#include "gobang.h"
#include <stdbool.h>
// ==================== 游戏核心变量 ====================
extern int BOARD_SIZE; // 当前实际使用的棋盘尺寸
extern int board[MAX_BOARD_SIZE][MAX_BOARD_SIZE]; // 棋盘状态存储数组
extern Step steps[MAX_STEPS]; // 存储所有落子步骤的数组
extern const int direction[4][2]; // 四个方向:向下、向右、右下、左下
extern int step_count; // 当前步数计数器
// ==================== 游戏配置变量 ====================
extern bool use_forbidden_moves; // 是否启用禁手规则的标志
extern int use_timer; // 是否启用计时器的标志
extern int time_limit; // 每回合的时间限制(秒,内部存储)
extern int network_port; // 网络端口
extern int network_timeout; // 网络超时时间
// ==================== AI相关变量 ====================
extern double defense_coefficient; // 防守系数
extern int ai_difficulty; // AI难度 (1-5)
// ==================== 网络相关变量 ====================
extern NetworkGameState network_state; // 网络游戏状态
// ==================== GUI相关变量 ====================
extern int current_player_gui; // GUI当前玩家
extern int game_over; // 游戏结束标志
extern char status_message[256]; // 状态消息
// ==================== 记录相关变量 ====================
extern int player1_final_score; // 玩家1最终得分
extern int player2_final_score; // 玩家2最终得分
extern int scores_calculated; // 评分计算标志
extern char winner_info[50]; // 存储胜负信息
#endif // GLOBALS_H
+6
View File
@@ -4,6 +4,7 @@
* @note * @note
* AI决策等功能 * AI决策等功能
*/ */
#ifndef GO_BANG_H #ifndef GO_BANG_H
#define GO_BANG_H #define GO_BANG_H
@@ -19,6 +20,11 @@
// 函数原型 // 函数原型
// --- 游戏核心逻辑 --- // --- 游戏核心逻辑 ---
/**
* @brief (EMPTY)
*/
void empty_board();
/** /**
* @brief * @brief
* @param x (0-based) * @param x (0-based)
+60
View File
@@ -0,0 +1,60 @@
/**
* @file gui.h
* @brief 图形化用户界面头文件
* @note 使用IUP库实现五子棋的图形化界面
* @author 刘航宇
*/
#ifndef GUI_H
#define GUI_H
#include "gobang.h"
#include "config.h"
#include "globals.h"
// GUI函数声明
/**
* @brief 初始化GUI
* @details 初始化IUP图形库和游戏界面组件
* @return 成功返回0,失败返回-1
*/
int init_gui();
/**
* @brief 清理GUI资源
*/
void cleanup_gui();
/**
* @brief 屏幕坐标转棋盘坐标
*/
int screen_to_board(int screen_x, int screen_y, int *board_x, int *board_y);
/**
* @brief 显示消息
*/
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
+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
+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 12
*/
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
+27 -23
View File
@@ -10,19 +10,15 @@
#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 player; // 执行该步的玩家标识
int x; // 落子的行坐标 (0-based) int x; // 落子的行坐标 (0-based)
int y; // 落子的列坐标 (0-based) int y; // 落子的列坐标 (0-based)
@@ -32,7 +28,8 @@ typedef struct {
* @brief * @brief
* @details * @details
*/ */
typedef struct { typedef struct
{
int continuous_chess; // 连续同色棋子的数量 int continuous_chess; // 连续同色棋子的数量
bool check_start; // 棋子序列的起始端是否为空位(即是否开放) bool check_start; // 棋子序列的起始端是否为空位(即是否开放)
bool check_end; // 棋子序列的末尾端是否为空位(即是否开放) bool check_end; // 棋子序列的末尾端是否为空位(即是否开放)
@@ -44,16 +41,18 @@ 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_NONE = 0, // 无威胁
THREAT_WIN = 5, // 直接获胜 THREAT_WIN = 5, // 直接获胜
THREAT_FOUR = 4, // 活四/冲四 THREAT_FOUR = 4, // 活四/冲四
@@ -68,9 +67,10 @@ typedef enum {
* @brief * @brief
* @details * @details
*/ */
typedef struct { typedef struct
int type; // 消息类型 {
int player_id; // 玩家ID int type; // 消息类型
int player_id; // 玩家ID
int x, y; // 坐标(用于落子) int x, y; // 坐标(用于落子)
char message[256]; // 消息内容(用于聊天等) char message[256]; // 消息内容(用于聊天等)
time_t timestamp; // 时间戳 time_t timestamp; // 时间戳
@@ -80,14 +80,18 @@ typedef struct {
* @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
-118
View File
@@ -1,118 +0,0 @@
#include "init_board.h"
#include "gobang.h"
#include "game_mode.h"
#include "config.h"
#include "globals.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @brief 初始化棋盘为全空状态并重置步数计数器
* 清空棋盘数组并将所有位置设为EMPTY,同时将step_count重置为0
*/
void empty_board()
{
// 初始化棋盘状态为全空
for (int i = 0; i < BOARD_SIZE; i++)
{
for (int j = 0; j < BOARD_SIZE; j++)
{
board[i][j] = EMPTY;
}
}
step_count = 0; // 重置步数计数器
}
/**
* @brief 打印当前棋盘状态
* 以可读格式输出棋盘,包括行列号和棋子状态
* 玩家棋子显示为'x'AI棋子显示为'○',空位显示为'·'
*/
void print_board()
{
// 打印列号(1-BOARD_SIZE显示)
printf("\n ");
for (int i = 0; i < BOARD_SIZE; i++)
{
printf("%2d", i + 1);
if (i + 1 == 9) // 处理列号9和10+的对齐
{
printf(" ");
}
}
printf("\n");
// 逐行打印棋盘内容
for (int i = 0; i < BOARD_SIZE; i++)
{
printf("%2d ", i + 1); // 打印行号(1-BOARD_SIZE
for (int j = 0; j < BOARD_SIZE; j++)
{
if (board[i][j] == PLAYER)
{
printf("x "); // 玩家棋子
}
else if (board[i][j] == AI)
{
printf(""); // AI棋子(使用○显示)
}
else
{
printf("· "); // 空位
}
}
printf("\n"); // 每行结束换行
}
}
/**
* @brief 配置棋盘大小
*
* @param player1 玩家1
* @param player2 玩家2
*/
void setup_board_size()
{
printf("通常棋盘大小分为休闲棋盘(13X13)、标准棋盘(15X15)和特殊棋盘(19X19)\n");
char prompt[100];
sprintf(prompt, "请输入棋盘大小(5~%d)(默认为标准棋盘):\n", MAX_BOARD_SIZE);
BOARD_SIZE = get_integer_input(prompt, 5, MAX_BOARD_SIZE);
}
/**
* @brief Set the up game options object
* 配置游戏选项,包括禁手规则、计时器和时间限制
*/
void setup_game_options()
{
use_forbidden_moves = get_integer_input("是否启用禁手规则 (1-是, 0-否): ", 0, 1);
use_timer = get_integer_input("是否启用计时器 (1-是, 0-否): ", 0, 1);
if (use_timer)
{
time_limit = get_integer_input("请输入每回合的时间限制 (1~60分钟): ", 1, 60) * 60;
}
}
/**
* @brief 确定先手玩家
*
* @param player1
* @param player2
* @return int player1 or player2
*/
int determine_first_player(int player1, int player2)
{
char prompt[100];
sprintf(prompt, "请选择先手方 (1 for Player %d, 2 for Player %d): ", player1, player2);
int first_player_choice = get_integer_input(prompt, 1, 2);
if (first_player_choice == 1)
{
return player1;
}
else
{
return player2;
}
}
-41
View File
@@ -1,41 +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
+43
View File
@@ -0,0 +1,43 @@
[Setup]
AppName=五子棋游戏
AppVersion=8.3
AppPublisher=LHY
AppPublisherURL=https://github.com/LHY0125/gobang.git
AppSupportURL=https://github.com/LHY0125/gobang.git
AppUpdatesURL=https://github.com/LHY0125/gobang.git
DefaultDirName={autopf}\Gobang
DefaultGroupName=五子棋游戏
AllowNoIcons=yes
OutputDir=dist
OutputBaseFilename=Gobang_Inno_Setup
SetupIconFile=
Compression=lzma
SolidCompression=yes
WizardStyle=modern
PrivilegesRequired=lowest
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "..\bin\gobang_gui.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\bin\iup.dll"; DestDir: "{app}"; Flags: ignoreversion
; 允许文件夹为空时不报错
Source: "..\bin\records\*"; DestDir: "{app}\records"; Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist
[Icons]
Name: "{group}\五子棋游戏(图形界面版)"; Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"
Name: "{group}\{cm:UninstallProgram,五子棋游戏}"; Filename: "{uninstallexe}"
Name: "{autodesktop}\五子棋游戏"; Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"; Tasks: desktopicon
[Run]
Filename: "{app}\gobang_gui.exe"; WorkingDir: "{app}"; Description: "{cm:LaunchProgram,五子棋游戏}"; Flags: nowait postinstall skipifsilent
[UninstallDelete]
Type: filesandordirs; Name: "{app}\records"
Type: files; Name: "{app}\gobang_gui.exe"
Type: files; Name: "{app}\iup.dll"
Type: dirifempty; Name: "{app}"
+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
@@ -0,0 +1,20 @@
/** \file
* \brief Binding of iupolecontrol to Lua.
*
* See Copyright Notice in "iup.h"
*/
#ifndef __IUPLUAOLE_H
#define __IUPLUAOLE_H
#ifdef __cplusplus
extern "C" {
#endif
int iupolelua_open (lua_State * L);
#ifdef __cplusplus
}
#endif
#endif

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