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

Contents of /lbbs/src/article_favor_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (show annotations)
Thu Oct 16 11:26:16 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.1: +7 -6 lines
Content type: text/x-csrc
Refine logging of KEY_NULL and KEY_TIMEOUT

1 /***************************************************************************
2 article_favor_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 "article_favor_display.h"
18 #include "article_view_log.h"
19 #include "io.h"
20 #include "log.h"
21 #include "login.h"
22 #include "screen.h"
23 #include "str_process.h"
24 #include "section_list.h"
25 #include "section_list_display.h"
26 #include "user_priv.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 LOCATE_ARTICLE,
35 CHANGE_PAGE,
36 SHOW_HELP,
37 SWITCH_NAME,
38 UNSET_FAVOR,
39 };
40
41 static int article_favor_draw_screen(int display_sname)
42 {
43 clearscr();
44 show_top("[主题收藏]", BBS_name, "");
45 moveto(2, 0);
46 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] "
47 "定位[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 移除[\033[1;32m-\033[0;37m\033[0;37m] "
48 "%s[\033[1;32mn\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
49 (display_sname ? "用户名" : "版块名称"));
50 moveto(3, 0);
51 if (display_sname)
52 {
53 prints("\033[44;37m \033[1;37m 编 号 版块名称 日 期 文章标题 \033[m");
54 }
55 else
56 {
57 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
58 }
59
60 return 0;
61 }
62
63 static int article_favor_draw_items(int page_id, ARTICLE *p_articles[], char p_snames[][BBS_section_name_max_len + 1],
64 int article_count, int display_sname)
65 {
66 char str_time[LINE_BUFFER_LEN];
67 struct tm tm_sub;
68 char title_f[BBS_article_title_max_len + 1];
69 int title_f_len;
70 int eol;
71 int len;
72 int i;
73 char article_flag;
74 int is_viewed;
75 time_t tm_now;
76
77 time(&tm_now);
78
79 clrline(4, 23);
80
81 for (i = 0; i < article_count; i++)
82 {
83 if (p_articles[i]->uid == BBS_priv.uid)
84 {
85 is_viewed = 1;
86 }
87 else
88 {
89 is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
90 if (is_viewed < 0)
91 {
92 log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
93 is_viewed = 0;
94 }
95 }
96
97 if (p_articles[i]->excerption)
98 {
99 article_flag = (is_viewed ? 'm' : 'M');
100 }
101 else if (p_articles[i]->lock && is_viewed)
102 {
103 article_flag = 'x';
104 }
105 else
106 {
107 article_flag = (is_viewed ? ' ' : 'N');
108 }
109
110 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
111 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
112 {
113 strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
114 }
115 else
116 {
117 strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
118 }
119
120 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
121 title_f[sizeof(title_f) - 1] = '\0';
122 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
123 strncat(title_f, p_articles[i]->title, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
124
125 len = split_line(title_f, 59 - (display_sname ? BBS_section_name_max_len : BBS_username_max_len), &eol, &title_f_len, 1);
126 if (title_f[len] != '\0')
127 {
128 title_f[len] = '\0';
129 }
130
131 moveto(4 + i, 1);
132
133 prints(" %7d %c %s%*s %s %s",
134 p_articles[i]->aid,
135 article_flag,
136 (display_sname ? p_snames[i] : p_articles[i]->username),
137 (display_sname
138 ? BBS_section_name_max_len - str_length(p_snames[i], 1)
139 : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
140 "",
141 str_time,
142 title_f);
143 }
144
145 return 0;
146 }
147
148 static enum select_cmd_t article_favor_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
149 {
150 int old_page_id = *p_page_id;
151 int old_selected_index = *p_selected_index;
152 int ch;
153
154 if (item_count > 0 && *p_selected_index >= 0)
155 {
156 moveto(4 + *p_selected_index, 1);
157 outc('>');
158 iflush();
159 }
160
161 while (!SYS_server_exit)
162 {
163 ch = igetch(100);
164
165 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
166 {
167 BBS_last_access_tm = time(NULL);
168 }
169
170 switch (ch)
171 {
172 case KEY_ESC:
173 case KEY_LEFT:
174 case KEY_NULL: // broken pipe
175 log_error("KEY_NULL\n");
176 return EXIT_LIST; // exit list
177 case KEY_TIMEOUT:
178 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
179 {
180 log_error("User input timeout\n");
181 return EXIT_LIST; // exit list
182 }
183 continue;
184 case 'n':
185 return SWITCH_NAME;
186 case '-':
187 if (item_count > 0)
188 {
189 return UNSET_FAVOR;
190 }
191 break;
192 case CR:
193 igetch_reset();
194 case KEY_RIGHT:
195 if (item_count > 0)
196 {
197 return LOCATE_ARTICLE;
198 }
199 break;
200 case KEY_HOME:
201 *p_page_id = 0;
202 case 'P':
203 case KEY_PGUP:
204 *p_selected_index = 0;
205 case 'k':
206 case KEY_UP:
207 if (*p_selected_index <= 0)
208 {
209 if (*p_page_id > 0)
210 {
211 (*p_page_id)--;
212 *p_selected_index = BBS_article_limit_per_page - 1;
213 }
214 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of list
215 {
216 if (total_page > 0)
217 {
218 *p_page_id = total_page - 1;
219 }
220 if (item_count > 0)
221 {
222 *p_selected_index = item_count - 1;
223 }
224 }
225 }
226 else
227 {
228 (*p_selected_index)--;
229 }
230 break;
231 case '$':
232 case KEY_END:
233 if (total_page > 0)
234 {
235 *p_page_id = total_page - 1;
236 }
237 case 'N':
238 case KEY_PGDN:
239 if (item_count > 0)
240 {
241 *p_selected_index = item_count - 1;
242 }
243 case 'j':
244 case KEY_DOWN:
245 if (*p_selected_index + 1 >= item_count) // next page
246 {
247 if (*p_page_id + 1 < total_page)
248 {
249 (*p_page_id)++;
250 *p_selected_index = 0;
251 }
252 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of list
253 {
254 *p_page_id = 0;
255 *p_selected_index = 0;
256 }
257 }
258 else
259 {
260 (*p_selected_index)++;
261 }
262 break;
263 case 'h':
264 return SHOW_HELP;
265 default:
266 }
267
268 if (old_page_id != *p_page_id)
269 {
270 return CHANGE_PAGE;
271 }
272
273 if (item_count > 0 && old_selected_index != *p_selected_index)
274 {
275 if (old_selected_index >= 0)
276 {
277 moveto(4 + old_selected_index, 1);
278 outc(' ');
279 }
280 if (*p_selected_index >= 0)
281 {
282 moveto(4 + *p_selected_index, 1);
283 outc('>');
284 }
285 iflush();
286
287 old_selected_index = *p_selected_index;
288 }
289 }
290
291 return EXIT_LIST;
292 }
293
294 int article_favor_display(ARTICLE_FAVOR *p_favor)
295 {
296 static int display_sname = 0;
297
298 char page_info_str[LINE_BUFFER_LEN];
299 char snames[BBS_article_limit_per_page][BBS_section_name_max_len + 1];
300 ARTICLE *p_articles[BBS_article_limit_per_page];
301 int article_count;
302 int page_count;
303 int page_id = 0;
304 int selected_index = 0;
305 int ret;
306
307 if (p_favor == NULL)
308 {
309 log_error("NULL pointer error\n");
310 return -1;
311 }
312
313 article_favor_draw_screen(display_sname);
314
315 ret = query_favor_articles(p_favor, page_id, p_articles, snames, &article_count, &page_count);
316 if (ret < 0)
317 {
318 log_error("query_favor_articles(page_id=%d) error\n", page_id);
319 return -2;
320 }
321
322 if (article_count == 0) // empty list
323 {
324 selected_index = 0;
325 }
326
327 while (!SYS_server_exit)
328 {
329 ret = article_favor_draw_items(page_id, p_articles, snames, article_count, display_sname);
330 if (ret < 0)
331 {
332 log_error("article_favor_draw_items(page_id=%d) error\n", page_id);
333 return -3;
334 }
335
336 snprintf(page_info_str, sizeof(page_info_str),
337 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
338 page_id + 1, MAX(page_count, 1));
339
340 show_bottom(page_info_str);
341 iflush();
342
343 if (user_online_update("ARTICLE_FAVOR") < 0)
344 {
345 log_error("user_online_update(ARTICLE_FAVOR) error\n");
346 }
347
348 ret = article_favor_select(page_count, article_count, &page_id, &selected_index);
349 switch (ret)
350 {
351 case EXIT_LIST:
352 return 0;
353 case UNSET_FAVOR:
354 if (article_favor_set(p_articles[selected_index]->aid, &BBS_article_favor, 0) != 1)
355 {
356 log_error("article_favor_set(aid=%d, 0) error\n", p_articles[selected_index]->aid);
357 break;
358 }
359 // continue to refresh list
360 case CHANGE_PAGE:
361 ret = query_favor_articles(p_favor, page_id, p_articles, snames, &article_count, &page_count);
362 if (ret < 0)
363 {
364 log_error("query_favor_articles(page_id=%d) error\n", page_id);
365 return -2;
366 }
367
368 if (article_count == 0) // empty list
369 {
370 selected_index = 0;
371 }
372 else if (selected_index >= article_count)
373 {
374 selected_index = article_count - 1;
375 }
376 break;
377 case LOCATE_ARTICLE:
378 if (section_list_display(snames[selected_index], p_articles[selected_index]->aid) < 0)
379 {
380 log_error("section_list_display(sname=%s, aid=%d) error\n",
381 snames[selected_index], p_articles[selected_index]->aid);
382 }
383 break;
384 case SWITCH_NAME:
385 display_sname = !display_sname;
386 article_favor_draw_screen(display_sname);
387 break;
388 case SHOW_HELP:
389 // Display help information
390 display_file(DATA_READ_HELP, 1);
391 article_favor_draw_screen(display_sname);
392 break;
393 default:
394 log_error("Unknown command %d\n", ret);
395 }
396 }
397
398 return 0;
399 }

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