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

Annotation of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.53 - (hide annotations)
Wed Oct 15 01:05:18 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.52: +56 -2 lines
Content type: text/x-csrc
Add article favor state display and set/unset in section article list

1 sysadm 1.1 /***************************************************************************
2     section_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 sysadm 1.9 #include "article_cache.h"
18 sysadm 1.53 #include "article_favor.h"
19 sysadm 1.41 #include "article_op.h"
20 sysadm 1.20 #include "article_post.h"
21 sysadm 1.34 #include "article_view_log.h"
22 sysadm 1.26 #include "article_del.h"
23 sysadm 1.1 #include "common.h"
24     #include "io.h"
25 sysadm 1.34 #include "log.h"
26     #include "login.h"
27 sysadm 1.37 #include "menu.h"
28 sysadm 1.48 #include "menu_proc.h"
29 sysadm 1.34 #include "section_list_display.h"
30     #include "section_list_loader.h"
31 sysadm 1.1 #include "screen.h"
32 sysadm 1.34 #include "str_process.h"
33 sysadm 1.18 #include "user_priv.h"
34 sysadm 1.29 #include <string.h>
35 sysadm 1.1 #include <time.h>
36 sysadm 1.6 #include <sys/param.h>
37 sysadm 1.1
38 sysadm 1.46 static int section_aid_locations[BBS_max_section] = {0};
39 sysadm 1.11 static int section_topic_view_mode = 0;
40 sysadm 1.13 static int section_topic_view_tid = -1;
41 sysadm 1.11
42 sysadm 1.1 enum select_cmd_t
43     {
44     EXIT_SECTION = 0,
45 sysadm 1.41 VIEW_ARTICLE,
46     CHANGE_PAGE,
47     SHOW_HELP,
48     CHANGE_NAME_DISPLAY,
49     POST_ARTICLE,
50     EDIT_ARTICLE,
51     DELETE_ARTICLE,
52     QUERY_ARTICLE,
53 sysadm 1.53 SET_FAVOR_ARTICLE,
54     UNSET_FAVOR_ARTICLE,
55 sysadm 1.41 FIRST_TOPIC_ARTICLE,
56     LAST_TOPIC_ARTICLE,
57 sysadm 1.45 SCAN_NEW_ARTICLE,
58 sysadm 1.41 VIEW_EX_DIR,
59 sysadm 1.48 SHOW_TOP10,
60 sysadm 1.1 };
61    
62 sysadm 1.36 static int section_list_draw_items(int page_id, ARTICLE *p_articles[], int article_count, int display_nickname, int ontop_start_offset)
63 sysadm 1.1 {
64     char str_time[LINE_BUFFER_LEN];
65     struct tm tm_sub;
66     char title_f[BBS_article_title_max_len + 1];
67     int title_f_len;
68     int eol;
69     int len;
70     int i;
71 sysadm 1.42 size_t j;
72 sysadm 1.3 char article_flag;
73 sysadm 1.17 int is_viewed;
74 sysadm 1.53 int is_favor;
75 sysadm 1.3 time_t tm_now;
76    
77     time(&tm_now);
78 sysadm 1.1
79     clrline(4, 23);
80    
81     for (i = 0; i < article_count; i++)
82     {
83 sysadm 1.18 if (p_articles[i]->uid == BBS_priv.uid)
84 sysadm 1.17 {
85 sysadm 1.18 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 sysadm 1.17 }
96    
97 sysadm 1.53 if (p_articles[i]->tid == 0)
98     {
99     is_favor = article_favor_check(p_articles[i]->aid, &BBS_article_favor);
100     if (is_favor < 0)
101     {
102     log_error("article_favor_check(aid=%d) error\n", p_articles[i]->aid);
103     is_favor = 0;
104     }
105     }
106     else
107     {
108     is_favor = 0;
109     }
110    
111 sysadm 1.3 if (p_articles[i]->excerption)
112     {
113 sysadm 1.17 article_flag = (is_viewed ? 'm' : 'M');
114 sysadm 1.3 }
115 sysadm 1.17 else if (p_articles[i]->lock && is_viewed)
116 sysadm 1.3 {
117     article_flag = 'x';
118     }
119 sysadm 1.35 else
120     {
121     article_flag = (is_viewed ? ' ' : 'N');
122     }
123 sysadm 1.3
124 sysadm 1.1 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
125 sysadm 1.3 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
126     {
127     strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
128     }
129     else
130     {
131     strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
132     }
133    
134 sysadm 1.40 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
135 sysadm 1.1 title_f[sizeof(title_f) - 1] = '\0';
136 sysadm 1.40 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
137 sysadm 1.42
138     // Rewrite title with "Re: Re: " prefix into "Re: ... "
139     j = 0;
140     if (p_articles[i]->tid != 0)
141     {
142     while (strncmp(p_articles[i]->title + j, "Re: ", strlen("Re: ")) == 0)
143     {
144     j += strlen("Re: ");
145     }
146     if (j >= strlen("Re: Re: "))
147     {
148     strncat(title_f, "Re: ... ", sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
149     }
150     else
151     {
152     j = 0;
153     }
154     }
155     strncat(title_f, p_articles[i]->title + j, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
156    
157 sysadm 1.51 len = split_line(title_f, 59 - (display_nickname ? BBS_nickname_max_len / 2 : BBS_username_max_len), &eol, &title_f_len, 1);
158 sysadm 1.1 if (title_f[len] != '\0')
159     {
160     title_f[len] = '\0';
161     }
162    
163     moveto(4 + i, 1);
164 sysadm 1.36 if (i >= ontop_start_offset)
165     {
166 sysadm 1.53 prints(" \033[1;33m[提示]\033[m%c%c %s%*s %s %s%s\033[m",
167     (is_favor ? '@' : ' '),
168 sysadm 1.36 article_flag,
169     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
170 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
171     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
172 sysadm 1.36 "",
173     str_time,
174     (p_articles[i]->aid == section_topic_view_tid
175     ? "\033[1;33m"
176     : (p_articles[i]->tid == section_topic_view_tid
177     ? "\033[1;36m"
178     : "")),
179     title_f);
180     }
181     else
182     {
183 sysadm 1.53 prints(" %s%7d\033[m%c%c %s%*s %s %s%s\033[m",
184 sysadm 1.36 (p_articles[i]->aid == section_topic_view_tid
185     ? "\033[1;33m"
186     : (p_articles[i]->tid == section_topic_view_tid
187     ? "\033[1;36m"
188     : "")),
189     p_articles[i]->aid,
190 sysadm 1.53 (is_favor ? '@' : ' '),
191 sysadm 1.36 article_flag,
192     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
193 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
194     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
195 sysadm 1.36 "",
196     str_time,
197     (p_articles[i]->aid == section_topic_view_tid
198     ? "\033[1;33m"
199     : (p_articles[i]->tid == section_topic_view_tid
200     ? "\033[1;36m"
201     : "")),
202     title_f);
203     }
204 sysadm 1.1 }
205    
206     return 0;
207     }
208    
209 sysadm 1.5 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
210 sysadm 1.1 {
211 sysadm 1.40 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
212 sysadm 1.1 char str_section_name[LINE_BUFFER_LEN];
213    
214 sysadm 1.5 if (master_list[0] != '\0')
215 sysadm 1.1 {
216 sysadm 1.40 snprintf(str_section_master, sizeof(str_section_master), "版主:%s", master_list);
217 sysadm 1.1 }
218 sysadm 1.40 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
219 sysadm 1.1
220     clearscr();
221 sysadm 1.5 show_top(str_section_master, stitle, str_section_name);
222 sysadm 1.1 moveto(2, 0);
223 sysadm 1.40 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] "
224     "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 发表[\033[1;32mCtrl-P\033[0;37m] "
225     "%s[\033[1;32mn\033[0;37m] 精华区[\033[1;32mx\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
226     (display_nickname ? "用户名" : "昵称"));
227 sysadm 1.1 moveto(3, 0);
228 sysadm 1.4 if (display_nickname)
229     {
230 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
231 sysadm 1.4 }
232     else
233     {
234 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
235 sysadm 1.4 }
236 sysadm 1.1
237     return 0;
238     }
239    
240     static enum select_cmd_t section_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
241     {
242     int old_page_id = *p_page_id;
243     int old_selected_index = *p_selected_index;
244     int ch;
245 sysadm 1.30 time_t last_refresh_tm = time(NULL);
246 sysadm 1.1
247     if (item_count > 0 && *p_selected_index >= 0)
248     {
249     moveto(4 + *p_selected_index, 1);
250     outc('>');
251     iflush();
252     }
253    
254     while (!SYS_server_exit)
255     {
256     ch = igetch(100);
257    
258     switch (ch)
259     {
260     case KEY_ESC:
261     case KEY_LEFT:
262 sysadm 1.30 BBS_last_access_tm = time(NULL);
263     case KEY_NULL: // broken pipe
264 sysadm 1.1 return EXIT_SECTION; // exit section
265     case KEY_TIMEOUT:
266 sysadm 1.30 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
267 sysadm 1.1 {
268     return EXIT_SECTION; // exit section
269     }
270     continue;
271 sysadm 1.4 case 'n':
272 sysadm 1.30 BBS_last_access_tm = time(NULL);
273 sysadm 1.4 return CHANGE_NAME_DISPLAY;
274 sysadm 1.1 case CR:
275     igetch_reset();
276 sysadm 1.28 case 'r':
277 sysadm 1.1 case KEY_RIGHT:
278     if (item_count > 0)
279     {
280 sysadm 1.30 BBS_last_access_tm = time(NULL);
281 sysadm 1.1 return VIEW_ARTICLE;
282     }
283     break;
284 sysadm 1.20 case Ctrl('P'):
285     return POST_ARTICLE;
286     case 'E':
287 sysadm 1.41 if (item_count > 0)
288     {
289     return EDIT_ARTICLE;
290     }
291     break;
292 sysadm 1.26 case 'd':
293 sysadm 1.41 if (item_count > 0)
294     {
295     return DELETE_ARTICLE;
296     }
297     break;
298     case Ctrl('Q'):
299     if (item_count > 0)
300     {
301     return QUERY_ARTICLE;
302     }
303     break;
304 sysadm 1.53 case 'F':
305     if (item_count > 0)
306     {
307     return SET_FAVOR_ARTICLE;
308     }
309     break;
310     case '-':
311     if (item_count > 0)
312     {
313     return UNSET_FAVOR_ARTICLE;
314     }
315     break;
316 sysadm 1.1 case KEY_HOME:
317     *p_page_id = 0;
318 sysadm 1.28 case 'P':
319 sysadm 1.1 case KEY_PGUP:
320     *p_selected_index = 0;
321 sysadm 1.28 case 'k':
322 sysadm 1.1 case KEY_UP:
323     if (*p_selected_index <= 0)
324     {
325     if (*p_page_id > 0)
326     {
327     (*p_page_id)--;
328     *p_selected_index = BBS_article_limit_per_page - 1;
329     }
330 sysadm 1.44 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of section list
331     {
332     if (total_page > 0)
333     {
334     *p_page_id = total_page - 1;
335     }
336     if (item_count > 0)
337     {
338     *p_selected_index = item_count - 1;
339     }
340     }
341 sysadm 1.1 }
342     else
343     {
344     (*p_selected_index)--;
345     }
346     break;
347 sysadm 1.28 case '$':
348 sysadm 1.1 case KEY_END:
349     if (total_page > 0)
350     {
351     *p_page_id = total_page - 1;
352     }
353 sysadm 1.28 case 'N':
354 sysadm 1.1 case KEY_PGDN:
355     if (item_count > 0)
356     {
357     *p_selected_index = item_count - 1;
358     }
359 sysadm 1.28 case 'j':
360 sysadm 1.1 case KEY_DOWN:
361     if (*p_selected_index + 1 >= item_count) // next page
362     {
363     if (*p_page_id + 1 < total_page)
364     {
365     (*p_page_id)++;
366     *p_selected_index = 0;
367     }
368 sysadm 1.44 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
369 sysadm 1.25 {
370 sysadm 1.44 *p_page_id = 0;
371     *p_selected_index = 0;
372 sysadm 1.25 }
373 sysadm 1.1 }
374     else
375     {
376     (*p_selected_index)++;
377     }
378     break;
379 sysadm 1.31 case '=':
380 sysadm 1.41 if (item_count > 0)
381     {
382     return FIRST_TOPIC_ARTICLE;
383     }
384     break;
385 sysadm 1.31 case '\\':
386 sysadm 1.41 if (item_count > 0)
387     {
388     return LAST_TOPIC_ARTICLE;
389     }
390     break;
391 sysadm 1.45 case 'S':
392     if (item_count > 0)
393     {
394     return SCAN_NEW_ARTICLE;
395     }
396     break;
397 sysadm 1.28 case 'h':
398     return SHOW_HELP;
399 sysadm 1.37 case 'x':
400     return VIEW_EX_DIR;
401 sysadm 1.49 case 'H':
402 sysadm 1.48 return SHOW_TOP10;
403 sysadm 1.1 default:
404     }
405    
406     if (old_page_id != *p_page_id)
407     {
408     return CHANGE_PAGE;
409     }
410    
411     if (item_count > 0 && old_selected_index != *p_selected_index)
412     {
413     if (old_selected_index >= 0)
414     {
415     moveto(4 + old_selected_index, 1);
416     outc(' ');
417     }
418     if (*p_selected_index >= 0)
419     {
420     moveto(4 + *p_selected_index, 1);
421     outc('>');
422     }
423     iflush();
424    
425     old_selected_index = *p_selected_index;
426     }
427    
428 sysadm 1.30 BBS_last_access_tm = time(NULL);
429     if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
430     {
431     return CHANGE_PAGE; // force section list refresh
432     }
433 sysadm 1.1 }
434    
435     return EXIT_SECTION;
436     }
437    
438 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
439 sysadm 1.10 {
440 sysadm 1.11 switch (*p_key)
441 sysadm 1.10 {
442 sysadm 1.11 case 'p':
443 sysadm 1.28 case Ctrl('X'):
444 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
445 sysadm 1.10 case 0: // Set msg
446 sysadm 1.11 if (section_topic_view_mode)
447 sysadm 1.10 {
448 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
449 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
450     "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
451     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
452 sysadm 1.10 }
453     else
454     {
455 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
456 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
457     "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
458     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
459 sysadm 1.10 }
460 sysadm 1.11 *p_key = 0;
461 sysadm 1.10 break;
462 sysadm 1.20 case 'r': // Reply article
463     return 1;
464 sysadm 1.31 case '=': // First topic article
465     return 1;
466     case '\\': // Last topic article
467     return 1;
468 sysadm 1.12 case KEY_UP:
469 sysadm 1.16 case KEY_PGUP:
470     case KEY_HOME:
471 sysadm 1.12 if (p_ctx->reach_begin)
472     {
473     if (section_topic_view_mode)
474     {
475     *p_key = KEY_PGUP;
476     }
477 sysadm 1.16 else
478     {
479     *p_key = KEY_UP;
480     }
481 sysadm 1.12 return 1;
482     }
483     break;
484 sysadm 1.28 case 'k':
485     if (section_topic_view_mode)
486     {
487     *p_key = KEY_PGUP;
488     }
489     else
490     {
491     *p_key = KEY_UP;
492     }
493     return 1;
494 sysadm 1.12 case KEY_DOWN:
495 sysadm 1.16 case KEY_PGDN:
496     case KEY_END:
497 sysadm 1.12 if (p_ctx->reach_end)
498     {
499     if (section_topic_view_mode)
500     {
501     *p_key = KEY_PGDN;
502     }
503 sysadm 1.16 else
504     {
505     *p_key = KEY_DOWN;
506     }
507 sysadm 1.12 return 1;
508     }
509     break;
510 sysadm 1.28 case 'j':
511     if (section_topic_view_mode)
512     {
513     *p_key = KEY_PGDN;
514     }
515     else
516     {
517     *p_key = KEY_DOWN;
518     }
519     return 1;
520 sysadm 1.10 }
521    
522     return 0;
523     }
524    
525 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
526 sysadm 1.1 {
527 sysadm 1.4 static int display_nickname = 0;
528    
529 sysadm 1.1 SECTION_LIST *p_section;
530 sysadm 1.46 int64_t section_index;
531     int32_t aid_location;
532 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
533     char master_list[(BBS_username_max_len + 1) * 3 + 1];
534 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
535 sysadm 1.1 ARTICLE *p_articles[BBS_article_limit_per_page];
536     int article_count;
537 sysadm 1.6 int page_count;
538 sysadm 1.36 int ontop_start_offset;
539 sysadm 1.1 int page_id = 0;
540     int selected_index = 0;
541 sysadm 1.10 ARTICLE_CACHE cache;
542 sysadm 1.1 int ret;
543 sysadm 1.12 int loop;
544     int direction;
545 sysadm 1.24 ARTICLE article_new;
546 sysadm 1.31 int page_id_cur;
547 sysadm 1.46 const ARTICLE *p_article_locate;
548 sysadm 1.1
549 sysadm 1.50 p_section = section_list_find_by_name(sname);
550 sysadm 1.1 if (p_section == NULL)
551     {
552     log_error("Section %s not found\n", sname);
553     return -1;
554     }
555    
556 sysadm 1.52 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
557     {
558     log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
559     p_section->sid, BBS_priv.uid);
560     return -1;
561     }
562    
563 sysadm 1.50 section_index = get_section_index(p_section);
564    
565 sysadm 1.5 if ((ret = section_list_rd_lock(p_section)) < 0)
566     {
567     log_error("section_list_rd_lock(sid = 0) error\n");
568     return -2;
569     }
570    
571     strncpy(stitle, p_section->stitle, sizeof(stitle) - 1);
572     stitle[sizeof(stitle) - 1] = '\0';
573     strncpy(master_list, p_section->master_list, sizeof(master_list) - 1);
574     master_list[sizeof(master_list) - 1] = '\0';
575    
576     if ((ret = section_list_rd_unlock(p_section)) < 0)
577     {
578     log_error("section_list_rd_unlock(sid = 0) error\n");
579     return -2;
580     }
581    
582 sysadm 1.46 if (aid == 0)
583     {
584     aid_location = section_aid_locations[section_index];
585     }
586     else
587     {
588     aid_location = aid;
589 sysadm 1.51 }
590 sysadm 1.46
591     // Locate at article with aid_locate
592     if (aid_location > 0)
593     {
594     p_article_locate = article_block_find_by_aid(aid_location);
595     if (p_article_locate == NULL)
596     {
597     log_error("article_block_find_by_aid(%d) error\n", aid_location);
598     return -3;
599     }
600    
601     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
602     &page_id, &selected_index, &article_count);
603     if (ret < 0)
604     {
605     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
606     p_section->sid, p_article_locate->aid);
607     return -3;
608     }
609     }
610    
611 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
612 sysadm 1.1 {
613     log_error("section_list_draw_screen() error\n");
614     return -2;
615     }
616    
617 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
618 sysadm 1.5 if (ret < 0)
619 sysadm 1.1 {
620 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
621     return -3;
622 sysadm 1.1 }
623 sysadm 1.5
624 sysadm 1.46 section_topic_view_tid = -1;
625    
626 sysadm 1.5 if (article_count == 0) // empty section
627 sysadm 1.1 {
628     selected_index = 0;
629     }
630 sysadm 1.46 else if (aid > 0)
631     {
632     // Update current topic
633     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
634    
635     // Update current aid location
636     section_aid_locations[section_index] = p_articles[selected_index]->aid;
637     }
638 sysadm 1.1
639     while (!SYS_server_exit)
640     {
641 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
642 sysadm 1.1 if (ret < 0)
643     {
644     log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
645     return -4;
646     }
647 sysadm 1.6
648 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
649 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
650 sysadm 1.7 page_id + 1, MAX(page_count, 1));
651 sysadm 1.8
652 sysadm 1.6 show_bottom(page_info_str);
653 sysadm 1.1 iflush();
654    
655 sysadm 1.33 if (user_online_update(sname) < 0)
656     {
657     log_error("user_online_update(%s) error\n", sname);
658     }
659    
660 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
661 sysadm 1.1 switch (ret)
662     {
663     case EXIT_SECTION:
664     return 0;
665     case CHANGE_PAGE:
666 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
667 sysadm 1.5 if (ret < 0)
668 sysadm 1.1 {
669 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
670     return -3;
671 sysadm 1.1 }
672 sysadm 1.5 if (article_count == 0) // empty section
673 sysadm 1.1 {
674     selected_index = 0;
675     }
676 sysadm 1.5 else if (selected_index >= article_count)
677 sysadm 1.1 {
678     selected_index = article_count - 1;
679     }
680     break;
681     case VIEW_ARTICLE:
682 sysadm 1.12 do
683 sysadm 1.9 {
684 sysadm 1.12 loop = 0;
685 sysadm 1.9
686 sysadm 1.12 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
687     {
688     log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
689     break;
690     }
691    
692 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
693     {
694     log_error("user_online_update(VIEW_ARTICLE) error\n");
695     }
696    
697 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
698 sysadm 1.12 display_article_key_handler, DATA_READ_HELP);
699    
700     if (article_cache_unload(&cache) < 0)
701     {
702     log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
703     break;
704     }
705    
706 sysadm 1.17 // Update article_view_log
707     if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
708     {
709     log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
710     }
711    
712 sysadm 1.12 switch (ret)
713     {
714     case KEY_UP:
715     if (selected_index <= 0)
716     {
717     if (page_id > 0)
718     {
719     page_id--;
720     selected_index = BBS_article_limit_per_page - 1;
721    
722 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
723 sysadm 1.12 if (ret < 0)
724     {
725     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
726     return -3;
727     }
728    
729     if (article_count != BBS_article_limit_per_page) // page is not full
730     {
731     selected_index = MAX(0, article_count - 1);
732     }
733     else
734     {
735     loop = 1;
736     }
737     }
738     }
739     else
740     {
741     selected_index--;
742     loop = 1;
743     }
744     break;
745     case KEY_DOWN:
746     if (selected_index + 1 >= article_count) // next page
747     {
748     if (page_id + 1 < page_count)
749     {
750     page_id++;
751     selected_index = 0;
752    
753 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
754 sysadm 1.12 if (ret < 0)
755     {
756     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
757     return -3;
758     }
759    
760     if (article_count == 0) // empty page
761     {
762     selected_index = 0;
763     }
764     else
765     {
766     loop = 1;
767     }
768     }
769     }
770     else
771     {
772     selected_index++;
773     loop = 1;
774     }
775     break;
776     case KEY_PGUP:
777     case KEY_PGDN:
778     direction = (ret == KEY_PGUP ? -1 : 1);
779 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
780     &page_id, &selected_index, &article_count);
781 sysadm 1.12 if (ret < 0)
782     {
783 sysadm 1.31 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
784 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
785     return -3;
786     }
787 sysadm 1.31 else if (ret > 0) // found
788 sysadm 1.12 {
789 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
790 sysadm 1.12 if (ret < 0)
791     {
792     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
793     return -3;
794     }
795     loop = 1;
796     }
797     break;
798 sysadm 1.20 case 'r': // Reply article
799 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
800     {
801     log_error("user_online_update(REPLY_ARTICLE) error\n");
802     }
803    
804 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
805 sysadm 1.20 {
806 sysadm 1.33 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
807 sysadm 1.20 }
808     loop = 1;
809     break;
810 sysadm 1.31 case '=': // First topic article
811     case '\\': // Last topic article
812     page_id_cur = page_id;
813     direction = (ret == '=' ? -1 : 1);
814     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
815     &page_id, &selected_index, &article_count);
816     if (ret < 0)
817     {
818     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
819     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
820     return -3;
821     }
822     else if (ret > 0) // found
823     {
824     if (page_id != page_id_cur) // page changed
825     {
826 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
827 sysadm 1.31 if (ret < 0)
828     {
829     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
830     return -3;
831     }
832     }
833     loop = 1;
834     }
835     break;
836 sysadm 1.12 }
837     } while (loop);
838 sysadm 1.13
839     // Update current topic
840     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
841 sysadm 1.46
842     // Update current aid location
843     section_aid_locations[section_index] = p_articles[selected_index]->aid;
844 sysadm 1.35
845     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
846     {
847     log_error("section_list_draw_screen() error\n");
848     return -2;
849     }
850     break;
851 sysadm 1.4 case CHANGE_NAME_DISPLAY:
852     display_nickname = !display_nickname;
853 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
854 sysadm 1.1 {
855     log_error("section_list_draw_screen() error\n");
856     return -2;
857     }
858     break;
859 sysadm 1.20 case POST_ARTICLE:
860 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
861     {
862     log_error("user_online_update(POST_ARTICLE) error\n");
863     }
864    
865 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
866 sysadm 1.20 {
867 sysadm 1.26 log_error("article_post(sid=%d) error\n", p_section->sid);
868 sysadm 1.20 }
869 sysadm 1.24 else if (ret > 0) // New article posted
870     {
871 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
872 sysadm 1.24 if (ret < 0)
873     {
874     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
875     return -3;
876     }
877     }
878 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
879     {
880     log_error("section_list_draw_screen() error\n");
881     return -2;
882     }
883     break;
884     case EDIT_ARTICLE:
885 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
886     p_articles[selected_index]->uid != BBS_priv.uid)
887 sysadm 1.20 {
888 sysadm 1.26 break; // No permission
889 sysadm 1.20 }
890 sysadm 1.33
891     if (user_online_update("EDIT_ARTICLE") < 0)
892     {
893     log_error("user_online_update() error\n");
894     }
895    
896 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
897 sysadm 1.20 {
898 sysadm 1.26 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
899     }
900     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
901     {
902     log_error("section_list_draw_screen() error\n");
903     return -2;
904     }
905     break;
906     case DELETE_ARTICLE:
907     if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
908     (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
909     {
910     break; // No permission
911     }
912 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
913 sysadm 1.26 {
914     log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
915 sysadm 1.20 }
916 sysadm 1.30 else if (ret > 0) // Article deleted
917     {
918 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
919 sysadm 1.30 if (ret < 0)
920     {
921     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
922     return -3;
923     }
924     }
925 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
926     {
927     log_error("section_list_draw_screen() error\n");
928     return -2;
929     }
930     break;
931 sysadm 1.41 case QUERY_ARTICLE:
932     if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
933     {
934     log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
935     }
936     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
937     {
938     log_error("section_list_draw_screen() error\n");
939     return -2;
940     }
941     break;
942 sysadm 1.53 case SET_FAVOR_ARTICLE:
943     ret = article_favor_set(p_articles[selected_index]->tid == 0
944     ? p_articles[selected_index]->aid
945     : p_articles[selected_index]->tid,
946     &BBS_article_favor, 1);
947     if (ret < 0)
948     {
949     log_error("article_favor_set(aid=%d, 1) error\n",
950     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
951     }
952     break;
953     case UNSET_FAVOR_ARTICLE:
954     ret = article_favor_set(p_articles[selected_index]->tid == 0
955     ? p_articles[selected_index]->aid
956     : p_articles[selected_index]->tid,
957     &BBS_article_favor, 0);
958     if (ret < 0)
959     {
960     log_error("article_favor_set(aid=%d, 0) error\n",
961     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
962     }
963     break;
964 sysadm 1.31 case FIRST_TOPIC_ARTICLE:
965     case LAST_TOPIC_ARTICLE:
966     page_id_cur = page_id;
967     direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
968     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
969     &page_id, &selected_index, &article_count);
970     if (ret < 0)
971     {
972     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
973     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
974     return -3;
975     }
976     else if (ret > 0 && page_id != page_id_cur) // found and page changed
977     {
978 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
979 sysadm 1.31 if (ret < 0)
980     {
981     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
982     return -3;
983     }
984     }
985     break;
986 sysadm 1.45 case SCAN_NEW_ARTICLE:
987 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
988 sysadm 1.45 if (ret < 0)
989     {
990     log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
991     p_section->sid, p_articles[selected_index]->aid);
992     return -3;
993     }
994     else if (ret == 0) // not found
995     {
996     break;
997     }
998     page_id_cur = page_id;
999 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1000 sysadm 1.45 &page_id, &selected_index, &article_count);
1001     if (ret < 0)
1002     {
1003     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1004 sysadm 1.46 p_section->sid, p_article_locate->aid);
1005 sysadm 1.45 return -3;
1006     }
1007     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1008     {
1009     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1010     if (ret < 0)
1011     {
1012     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1013     return -3;
1014     }
1015     }
1016     break;
1017 sysadm 1.28 case SHOW_HELP:
1018     // Display help information
1019     display_file(DATA_READ_HELP, 1);
1020     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1021     {
1022     log_error("section_list_draw_screen() error\n");
1023     return -2;
1024     }
1025     break;
1026 sysadm 1.37 case VIEW_EX_DIR:
1027     if (section_list_ex_dir_display(p_section) < 0)
1028     {
1029     log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
1030     }
1031     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1032     {
1033     log_error("section_list_draw_screen() error\n");
1034     return -2;
1035     }
1036     break;
1037 sysadm 1.48 case SHOW_TOP10:
1038     show_top10_menu(NULL);
1039     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1040     {
1041     log_error("section_list_draw_screen() error\n");
1042     return -2;
1043     }
1044     break;
1045 sysadm 1.1 default:
1046     log_error("Unknown command %d\n", ret);
1047     }
1048     }
1049    
1050     return 0;
1051     }
1052 sysadm 1.37
1053     int section_list_ex_dir_display(SECTION_LIST *p_section)
1054     {
1055     MENU_SET ex_menu_set;
1056     int ch = 0;
1057    
1058     if (p_section == NULL)
1059     {
1060     log_error("NULL pointer error\n");
1061     return -1;
1062     }
1063    
1064 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1065     {
1066     moveto(2, 1);
1067     clrtoeol();
1068 sysadm 1.40 prints("该版块精华区未开放");
1069 sysadm 1.39 press_any_key();
1070     return 0;
1071     }
1072    
1073 sysadm 1.37 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1074     {
1075     log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1076     return -3;
1077     }
1078     if (get_menu_shm_readonly(&ex_menu_set) < 0)
1079     {
1080 sysadm 1.39 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1081 sysadm 1.37 return -3;
1082     }
1083    
1084     clearscr();
1085 sysadm 1.38 show_bottom("");
1086 sysadm 1.37
1087     if (display_menu(&ex_menu_set) == 0)
1088     {
1089     while (!SYS_server_exit)
1090     {
1091     iflush();
1092     ch = igetch(100);
1093     switch (ch)
1094     {
1095     case KEY_NULL: // broken pipe
1096     return 0;
1097     case KEY_TIMEOUT:
1098     if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
1099     {
1100     return 0;
1101     }
1102     continue;
1103     case CR:
1104     igetch_reset();
1105     default:
1106     switch (menu_control(&ex_menu_set, ch))
1107     {
1108     case EXITMENU:
1109     ch = EXITMENU;
1110     break;
1111     case REDRAW:
1112     clearscr();
1113 sysadm 1.38 show_bottom("");
1114 sysadm 1.37 display_menu(&ex_menu_set);
1115     break;
1116     case NOREDRAW:
1117     case UNKNOWN_CMD:
1118     default:
1119     break;
1120     }
1121     }
1122    
1123     BBS_last_access_tm = time(NULL);
1124    
1125     if (ch == EXITMENU)
1126     {
1127     break;
1128     }
1129     }
1130     }
1131    
1132     detach_menu_shm(&ex_menu_set);
1133    
1134     return 0;
1135     }

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