/[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.46 - (show annotations)
Mon Oct 13 02:23:27 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.45: +52 -6 lines
Content type: text/x-csrc
Support locate at specific article while listing section articles
Remember last located article of each section, before logout

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

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