/[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.13 - (show annotations)
Tue Oct 28 05:02:17 2025 UTC (4 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.12: +6 -6 lines
Content type: text/x-csrc
Refine date/time display format

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

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