/[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.1 - (show annotations)
Wed Oct 15 00:45:21 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Content type: text/x-csrc
Update favor list display, support unset favor

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 switch (ch)
166 {
167 case KEY_ESC:
168 case KEY_LEFT:
169 BBS_last_access_tm = time(NULL);
170 case KEY_NULL: // broken pipe
171 return EXIT_LIST; // exit list
172 case KEY_TIMEOUT:
173 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
174 {
175 return EXIT_LIST; // exit list
176 }
177 continue;
178 case 'n':
179 BBS_last_access_tm = time(NULL);
180 return SWITCH_NAME;
181 case '-':
182 if (item_count > 0)
183 {
184 BBS_last_access_tm = time(NULL);
185 return UNSET_FAVOR;
186 }
187 break;
188 case CR:
189 igetch_reset();
190 case KEY_RIGHT:
191 if (item_count > 0)
192 {
193 BBS_last_access_tm = time(NULL);
194 return LOCATE_ARTICLE;
195 }
196 break;
197 case KEY_HOME:
198 *p_page_id = 0;
199 case 'P':
200 case KEY_PGUP:
201 *p_selected_index = 0;
202 case 'k':
203 case KEY_UP:
204 if (*p_selected_index <= 0)
205 {
206 if (*p_page_id > 0)
207 {
208 (*p_page_id)--;
209 *p_selected_index = BBS_article_limit_per_page - 1;
210 }
211 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of list
212 {
213 if (total_page > 0)
214 {
215 *p_page_id = total_page - 1;
216 }
217 if (item_count > 0)
218 {
219 *p_selected_index = item_count - 1;
220 }
221 }
222 }
223 else
224 {
225 (*p_selected_index)--;
226 }
227 break;
228 case '$':
229 case KEY_END:
230 if (total_page > 0)
231 {
232 *p_page_id = total_page - 1;
233 }
234 case 'N':
235 case KEY_PGDN:
236 if (item_count > 0)
237 {
238 *p_selected_index = item_count - 1;
239 }
240 case 'j':
241 case KEY_DOWN:
242 if (*p_selected_index + 1 >= item_count) // next page
243 {
244 if (*p_page_id + 1 < total_page)
245 {
246 (*p_page_id)++;
247 *p_selected_index = 0;
248 }
249 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of list
250 {
251 *p_page_id = 0;
252 *p_selected_index = 0;
253 }
254 }
255 else
256 {
257 (*p_selected_index)++;
258 }
259 break;
260 case 'h':
261 return SHOW_HELP;
262 default:
263 }
264
265 if (old_page_id != *p_page_id)
266 {
267 return CHANGE_PAGE;
268 }
269
270 if (item_count > 0 && old_selected_index != *p_selected_index)
271 {
272 if (old_selected_index >= 0)
273 {
274 moveto(4 + old_selected_index, 1);
275 outc(' ');
276 }
277 if (*p_selected_index >= 0)
278 {
279 moveto(4 + *p_selected_index, 1);
280 outc('>');
281 }
282 iflush();
283
284 old_selected_index = *p_selected_index;
285 }
286
287 BBS_last_access_tm = time(NULL);
288 }
289
290 return EXIT_LIST;
291 }
292
293 int article_favor_display(ARTICLE_FAVOR *p_favor)
294 {
295 static int display_sname = 0;
296
297 char page_info_str[LINE_BUFFER_LEN];
298 char snames[BBS_article_limit_per_page][BBS_section_name_max_len + 1];
299 ARTICLE *p_articles[BBS_article_limit_per_page];
300 int article_count;
301 int page_count;
302 int page_id = 0;
303 int selected_index = 0;
304 int ret;
305
306 if (p_favor == NULL)
307 {
308 log_error("NULL pointer error\n");
309 return -1;
310 }
311
312 article_favor_draw_screen(display_sname);
313
314 ret = query_favor_articles(p_favor, page_id, p_articles, snames, &article_count, &page_count);
315 if (ret < 0)
316 {
317 log_error("query_favor_articles(page_id=%d) error\n", page_id);
318 return -2;
319 }
320
321 if (article_count == 0) // empty list
322 {
323 selected_index = 0;
324 }
325
326 while (!SYS_server_exit)
327 {
328 ret = article_favor_draw_items(page_id, p_articles, snames, article_count, display_sname);
329 if (ret < 0)
330 {
331 log_error("article_favor_draw_items(page_id=%d) error\n", page_id);
332 return -3;
333 }
334
335 snprintf(page_info_str, sizeof(page_info_str),
336 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
337 page_id + 1, MAX(page_count, 1));
338
339 show_bottom(page_info_str);
340 iflush();
341
342 if (user_online_update("ARTICLE_FAVOR") < 0)
343 {
344 log_error("user_online_update(ARTICLE_FAVOR) error\n");
345 }
346
347 ret = article_favor_select(page_count, article_count, &page_id, &selected_index);
348 switch (ret)
349 {
350 case EXIT_LIST:
351 return 0;
352 case UNSET_FAVOR:
353 if (article_favor_set(p_articles[selected_index]->aid, &BBS_article_favor, 0) != 1)
354 {
355 log_error("article_favor_set(aid=%d, 0) error\n", p_articles[selected_index]->aid);
356 break;
357 }
358 // continue to refresh list
359 case CHANGE_PAGE:
360 ret = query_favor_articles(p_favor, page_id, p_articles, snames, &article_count, &page_count);
361 if (ret < 0)
362 {
363 log_error("query_favor_articles(page_id=%d) error\n", page_id);
364 return -2;
365 }
366
367 if (article_count == 0) // empty list
368 {
369 selected_index = 0;
370 }
371 else if (selected_index >= article_count)
372 {
373 selected_index = article_count - 1;
374 }
375 break;
376 case LOCATE_ARTICLE:
377 if (section_list_display(snames[selected_index], p_articles[selected_index]->aid) < 0)
378 {
379 log_error("section_list_display(sname=%s, aid=%d) error\n",
380 snames[selected_index], p_articles[selected_index]->aid);
381 }
382 break;
383 case SWITCH_NAME:
384 display_sname = !display_sname;
385 article_favor_draw_screen(display_sname);
386 break;
387 case SHOW_HELP:
388 // Display help information
389 display_file(DATA_READ_HELP, 1);
390 article_favor_draw_screen(display_sname);
391 break;
392 default:
393 log_error("Unknown command %d\n", ret);
394 }
395 }
396
397 return 0;
398 }

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