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

Contents of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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

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