/[LeafOK_CVS]/lbbs/src/user_list_display.c
ViewVC logotype

Contents of /lbbs/src/user_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.7 - (show annotations)
Wed Oct 22 14:25:15 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.6: +21 -20 lines
Content type: text/x-csrc
Fix bug

1 /***************************************************************************
2 user_list_display.c - description
3 -------------------
4 Copyright : (C) 2004-2025 by Leaflet
5 Email : leaflet@leafok.com
6 ***************************************************************************/
7
8 /***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 3 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17 #include "common.h"
18 #include "io.h"
19 #include "log.h"
20 #include "login.h"
21 #include "screen.h"
22 #include "str_process.h"
23 #include "user_list.h"
24 #include "user_priv.h"
25 #include "user_list_display.h"
26 #include <string.h>
27 #include <time.h>
28 #include <sys/param.h>
29
30 enum select_cmd_t
31 {
32 EXIT_LIST = 0,
33 VIEW_USER,
34 CHANGE_PAGE,
35 REFRESH_LIST,
36 SHOW_HELP,
37 };
38
39 static int user_list_draw_screen(int online_user)
40 {
41 clearscr();
42 show_top((online_user ? "[线上使用者]" : "[已注册用户]"), BBS_name, "");
43 moveto(2, 0);
44 prints("返回[\033[1;32m←\033[0;37m,\033[1;32mESC\033[0;37m] 选择[\033[1;32m↑\033[0;37m,\033[1;32m↓\033[0;37m] "
45 "查看[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m");
46 moveto(3, 0);
47
48 if (online_user)
49 {
50 prints("\033[44;37m \033[1;37m 编 号 用户名 昵称 在线时长 空闲 最后活动 \033[m");
51 }
52 else
53 {
54 prints("\033[44;37m \033[1;37m 编 号 用户名 昵称 上次登陆距今 \033[m");
55 }
56
57 return 0;
58 }
59
60 static int user_list_draw_items(int page_id, USER_INFO *p_users, int user_count)
61 {
62 char str_time_login[LINE_BUFFER_LEN];
63 time_t tm_now;
64 time_t tm_duration;
65 struct tm *p_tm;
66 int i;
67
68 clrline(4, 23);
69
70 time(&tm_now);
71
72 for (i = 0; i < user_count; i++)
73 {
74 tm_duration = tm_now - p_users[i].last_login_dt;
75 p_tm = gmtime(&tm_duration);
76 if (p_tm == NULL)
77 {
78 log_error("Invalid time duration\n");
79 str_time_login[0] = '\0';
80 }
81 else if (p_tm->tm_year > 70)
82 {
83 snprintf(str_time_login, sizeof(str_time_login),
84 "%d年", p_tm->tm_year - 70);
85 }
86 else if (p_tm->tm_yday > 0)
87 {
88 snprintf(str_time_login, sizeof(str_time_login),
89 "%d天", p_tm->tm_yday);
90 }
91 else if (p_tm->tm_hour > 0)
92 {
93 snprintf(str_time_login, sizeof(str_time_login),
94 "%d时%d分", p_tm->tm_hour, p_tm->tm_min);
95 }
96 else
97 {
98 snprintf(str_time_login, sizeof(str_time_login),
99 "%d分%d秒", p_tm->tm_min, p_tm->tm_sec);
100 }
101
102 moveto(4 + i, 1);
103
104 prints(" %6d %s%*s %s%*s %s",
105 p_users[i].id + 1,
106 p_users[i].username,
107 BBS_username_max_len - str_length(p_users[i].username, 1),
108 "",
109 p_users[i].nickname,
110 BBS_nickname_max_len / 2 - str_length(p_users[i].nickname, 1),
111 "",
112 str_time_login);
113 }
114
115 return 0;
116 }
117
118 static int user_online_list_draw_items(int page_id, USER_ONLINE_INFO *p_users, int user_count)
119 {
120 char str_time_login[LINE_BUFFER_LEN];
121 char str_time_idle[LINE_BUFFER_LEN];
122 const char *p_action_title;
123 time_t tm_now;
124 time_t tm_duration;
125 struct tm *p_tm;
126 int i;
127
128 clrline(4, 23);
129
130 time(&tm_now);
131
132 for (i = 0; i < user_count; i++)
133 {
134 tm_duration = tm_now - p_users[i].login_tm;
135 p_tm = gmtime(&tm_duration);
136 if (p_tm == NULL)
137 {
138 log_error("Invalid time duration\n");
139 str_time_login[0] = '\0';
140 }
141 else if (p_tm->tm_yday > 0)
142 {
143 snprintf(str_time_login, sizeof(str_time_login),
144 "%d天%d时", p_tm->tm_yday, p_tm->tm_hour);
145 }
146 else if (p_tm->tm_hour > 0)
147 {
148 snprintf(str_time_login, sizeof(str_time_login),
149 "%d时%d分", p_tm->tm_hour, p_tm->tm_min);
150 }
151 else
152 {
153 snprintf(str_time_login, sizeof(str_time_login),
154 "%d\'%d\"", p_tm->tm_min, p_tm->tm_sec);
155 }
156
157 tm_duration = tm_now - p_users[i].last_tm;
158 p_tm = gmtime(&tm_duration);
159 if (p_tm == NULL)
160 {
161 log_error("Invalid time duration\n");
162 str_time_idle[0] = '\0';
163 }
164 else if (p_tm->tm_min > 0)
165 {
166 snprintf(str_time_idle, sizeof(str_time_idle),
167 "%d\'%d\"", p_tm->tm_min, p_tm->tm_sec);
168 }
169 else
170 {
171 snprintf(str_time_idle, sizeof(str_time_idle),
172 "%d\"", p_tm->tm_sec);
173 }
174
175 p_action_title = (p_users[i].current_action_title != NULL
176 ? p_users[i].current_action_title
177 : p_users[i].current_action);
178
179 moveto(4 + i, 1);
180
181 prints(" %6d %s%*s %s%*s %s%*s %s%*s %s",
182 p_users[i].id + 1,
183 p_users[i].user_info.username,
184 BBS_username_max_len - str_length(p_users[i].user_info.username, 1),
185 "",
186 p_users[i].user_info.nickname,
187 BBS_nickname_max_len / 2 - str_length(p_users[i].user_info.nickname, 1),
188 "",
189 str_time_login,
190 8 - str_length(str_time_login, 1),
191 "",
192 str_time_idle,
193 6 - str_length(str_time_idle, 1),
194 "",
195 p_action_title);
196 }
197
198 return 0;
199 }
200
201 static enum select_cmd_t user_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
202 {
203 int old_page_id = *p_page_id;
204 int old_selected_index = *p_selected_index;
205 int ch;
206
207 if (item_count > 0 && *p_selected_index >= 0)
208 {
209 moveto(4 + *p_selected_index, 1);
210 outc('>');
211 iflush();
212 }
213
214 while (!SYS_server_exit)
215 {
216 ch = igetch(100);
217
218 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
219 {
220 BBS_last_access_tm = time(NULL);
221 }
222
223 switch (ch)
224 {
225 case KEY_NULL: // broken pipe
226 log_error("KEY_NULL\n");
227 case KEY_ESC:
228 case KEY_LEFT:
229 return EXIT_LIST; // exit list
230 case KEY_TIMEOUT:
231 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
232 {
233 log_error("User input timeout\n");
234 return EXIT_LIST; // exit list
235 }
236 continue;
237 case CR:
238 case KEY_RIGHT:
239 if (item_count > 0)
240 {
241 return VIEW_USER;
242 }
243 break;
244 case KEY_HOME:
245 *p_page_id = 0;
246 case 'P':
247 case KEY_PGUP:
248 *p_selected_index = 0;
249 case 'k':
250 case KEY_UP:
251 if (*p_selected_index <= 0)
252 {
253 if (*p_page_id > 0)
254 {
255 (*p_page_id)--;
256 *p_selected_index = BBS_user_limit_per_page - 1;
257 }
258 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of list
259 {
260 if (total_page > 0)
261 {
262 *p_page_id = total_page - 1;
263 }
264 if (item_count > 0)
265 {
266 *p_selected_index = item_count - 1;
267 }
268 }
269 }
270 else
271 {
272 (*p_selected_index)--;
273 }
274 break;
275 case '$':
276 case KEY_END:
277 if (total_page > 0)
278 {
279 *p_page_id = total_page - 1;
280 }
281 case 'N':
282 case KEY_PGDN:
283 if (item_count > 0)
284 {
285 *p_selected_index = item_count - 1;
286 }
287 case 'j':
288 case KEY_DOWN:
289 if (*p_selected_index + 1 >= item_count) // next page
290 {
291 if (*p_page_id + 1 < total_page)
292 {
293 (*p_page_id)++;
294 *p_selected_index = 0;
295 }
296 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of list
297 {
298 *p_page_id = 0;
299 *p_selected_index = 0;
300 }
301 }
302 else
303 {
304 (*p_selected_index)++;
305 }
306 break;
307 case KEY_F5:
308 return REFRESH_LIST;
309 case 'h':
310 return SHOW_HELP;
311 default:
312 break;
313 }
314
315 if (old_page_id != *p_page_id)
316 {
317 return CHANGE_PAGE;
318 }
319
320 if (item_count > 0 && old_selected_index != *p_selected_index)
321 {
322 if (old_selected_index >= 0)
323 {
324 moveto(4 + old_selected_index, 1);
325 outc(' ');
326 }
327 if (*p_selected_index >= 0)
328 {
329 moveto(4 + *p_selected_index, 1);
330 outc('>');
331 }
332 iflush();
333
334 old_selected_index = *p_selected_index;
335 }
336 }
337
338 return EXIT_LIST;
339 }
340
341 int user_list_display(int online_user)
342 {
343 char page_info_str[LINE_BUFFER_LEN];
344 USER_INFO users[BBS_user_limit_per_page];
345 USER_ONLINE_INFO online_users[BBS_user_limit_per_page];
346 int user_count = 0;
347 int page_count = 0;
348 int page_id = 0;
349 int selected_index = 0;
350 int ret = 0;
351
352 user_list_draw_screen(online_user);
353
354 if (online_user)
355 {
356 ret = query_user_online_list(page_id, online_users, &user_count, &page_count);
357 if (ret < 0)
358 {
359 log_error("query_user_online_list(page_id=%d) error\n", page_id);
360 return -2;
361 }
362 }
363 else
364 {
365 ret = query_user_list(page_id, users, &user_count, &page_count);
366 if (ret < 0)
367 {
368 log_error("query_user_list(page_id=%d) error\n", page_id);
369 return -2;
370 }
371 }
372
373 if (user_count == 0) // empty list
374 {
375 selected_index = 0;
376 }
377
378 while (!SYS_server_exit)
379 {
380 if (online_user)
381 {
382 ret = user_online_list_draw_items(page_id, online_users, user_count);
383 if (ret < 0)
384 {
385 log_error("user_online_list_draw_items(page_id=%d) error\n", page_id);
386 return -3;
387 }
388 }
389 else
390 {
391 ret = user_list_draw_items(page_id, users, user_count);
392 if (ret < 0)
393 {
394 log_error("user_list_draw_items(page_id=%d) error\n", page_id);
395 return -3;
396 }
397 }
398
399 snprintf(page_info_str, sizeof(page_info_str),
400 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
401 page_id + 1, MAX(page_count, 1));
402
403 show_bottom(page_info_str);
404 iflush();
405
406 if (user_online_update(online_user ? "USER_ONLINE" : "USER_LIST") < 0)
407 {
408 log_error("user_online_update(%s) error\n",
409 (online_user ? "USER_ONLINE" : "USER_LIST"));
410 }
411
412 ret = user_list_select(page_count, user_count, &page_id, &selected_index);
413 switch (ret)
414 {
415 case EXIT_LIST:
416 return 0;
417 case REFRESH_LIST:
418 case CHANGE_PAGE:
419 if (online_user)
420 {
421 ret = query_user_online_list(page_id, online_users, &user_count, &page_count);
422 if (ret < 0)
423 {
424 log_error("query_user_online_list(page_id=%d) error\n", page_id);
425 return -2;
426 }
427 }
428 else
429 {
430 ret = query_user_list(page_id, users, &user_count, &page_count);
431 if (ret < 0)
432 {
433 log_error("query_user_list(page_id=%d) error\n", page_id);
434 return -2;
435 }
436 }
437
438 if (user_count == 0) // empty list
439 {
440 selected_index = 0;
441 }
442 else if (selected_index >= user_count)
443 {
444 selected_index = user_count - 1;
445 }
446 break;
447 case VIEW_USER:
448 clearscr();
449 if (online_user)
450 {
451 prints("已选中用户 [%s] 会话 %d", online_users[selected_index].user_info.username, online_users[selected_index].id);
452
453 // USER_ONLINE_INFO users[5];
454 // int user_cnt = 5;
455 // ret = query_user_online_info_by_uid(online_users[selected_index].user_info.uid, users, &user_cnt, 0);
456 // if (ret <= 0)
457 // {
458 // log_error("query_user_online_info_by_uid(uid=%d, cnt=%d) error: %d\n",
459 // online_users[selected_index].user_info.uid, user_cnt, ret);
460 // }
461 // else
462 // {
463 // for (int i = 0; i < user_cnt; i++)
464 // {
465 // moveto(2 + i, 1);
466 // prints("会话%d", users[i].id);
467 // }
468 // }
469 }
470 else
471 {
472 prints("已选中用户 [%s]", users[selected_index].username);
473 }
474 press_any_key();
475 user_list_draw_screen(online_user);
476 break;
477 case SHOW_HELP:
478 // Display help information
479 display_file(DATA_READ_HELP, 1);
480 user_list_draw_screen(online_user);
481 break;
482 default:
483 log_error("Unknown command %d\n", ret);
484 }
485 }
486
487 return 0;
488 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1