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

Annotation of /lbbs/src/section_list_display.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.55 - (hide annotations)
Fri Oct 17 01:25:08 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.54: +0 -2 lines
Content type: text/x-csrc
No longer use igetch_reset() to skip remaining \n after \r
\r\n -> \r and \n -> \r conversions have already been implemented in igetch()

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

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