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

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