/[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.57 - (show annotations)
Sat Oct 25 13:09:42 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.56: +33 -1 lines
Content type: text/x-csrc
Press Ctrl-A in section list to display user information of selected article

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

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