/[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.45 - (show annotations)
Sat Oct 4 03:21:59 2025 UTC (5 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.44: +39 -0 lines
Content type: text/x-csrc
Locate at next unread article by pressing 'S' in article list

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

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