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

Annotation of /lbbs/src/article_favor_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.12 - (hide annotations)
Wed Dec 17 03:47:00 2025 UTC (2 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.11: +2 -0 lines
Content type: text/x-csrc
Refine debug log

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

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