/[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.10 - (show annotations)
Thu Oct 23 05:03:19 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.9: +24 -7 lines
Content type: text/x-csrc
Display user introduction for testing

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

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