/[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.56 - (hide annotations)
Sat Oct 18 12:06:10 2025 UTC (4 months, 4 weeks ago) by sysadm
Branch: MAIN
Changes since 1.55: +1 -0 lines
Content type: text/x-csrc
Refine code to keep compatible with gcc -Wpedantic option

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 sysadm 1.56 break;
409 sysadm 1.1 }
410    
411     if (old_page_id != *p_page_id)
412     {
413     return CHANGE_PAGE;
414     }
415    
416     if (item_count > 0 && old_selected_index != *p_selected_index)
417     {
418     if (old_selected_index >= 0)
419     {
420     moveto(4 + old_selected_index, 1);
421     outc(' ');
422     }
423     if (*p_selected_index >= 0)
424     {
425     moveto(4 + *p_selected_index, 1);
426     outc('>');
427     }
428     iflush();
429    
430     old_selected_index = *p_selected_index;
431     }
432    
433 sysadm 1.30 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
434     {
435     return CHANGE_PAGE; // force section list refresh
436     }
437 sysadm 1.1 }
438    
439     return EXIT_SECTION;
440     }
441    
442 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
443 sysadm 1.10 {
444 sysadm 1.11 switch (*p_key)
445 sysadm 1.10 {
446 sysadm 1.11 case 'p':
447 sysadm 1.28 case Ctrl('X'):
448 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
449 sysadm 1.10 case 0: // Set msg
450 sysadm 1.11 if (section_topic_view_mode)
451 sysadm 1.10 {
452 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
453 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
454     "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
455     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
456 sysadm 1.10 }
457     else
458     {
459 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
460 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
461     "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
462     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
463 sysadm 1.10 }
464 sysadm 1.11 *p_key = 0;
465 sysadm 1.10 break;
466 sysadm 1.20 case 'r': // Reply article
467     return 1;
468 sysadm 1.31 case '=': // First topic article
469     return 1;
470     case '\\': // Last topic article
471     return 1;
472 sysadm 1.12 case KEY_UP:
473 sysadm 1.16 case KEY_PGUP:
474     case KEY_HOME:
475 sysadm 1.12 if (p_ctx->reach_begin)
476     {
477     if (section_topic_view_mode)
478     {
479     *p_key = KEY_PGUP;
480     }
481 sysadm 1.16 else
482     {
483     *p_key = KEY_UP;
484     }
485 sysadm 1.12 return 1;
486     }
487     break;
488 sysadm 1.28 case 'k':
489     if (section_topic_view_mode)
490     {
491     *p_key = KEY_PGUP;
492     }
493     else
494     {
495     *p_key = KEY_UP;
496     }
497     return 1;
498 sysadm 1.12 case KEY_DOWN:
499 sysadm 1.16 case KEY_PGDN:
500     case KEY_END:
501 sysadm 1.12 if (p_ctx->reach_end)
502     {
503     if (section_topic_view_mode)
504     {
505     *p_key = KEY_PGDN;
506     }
507 sysadm 1.16 else
508     {
509     *p_key = KEY_DOWN;
510     }
511 sysadm 1.12 return 1;
512     }
513     break;
514 sysadm 1.28 case 'j':
515     if (section_topic_view_mode)
516     {
517     *p_key = KEY_PGDN;
518     }
519     else
520     {
521     *p_key = KEY_DOWN;
522     }
523     return 1;
524 sysadm 1.10 }
525    
526     return 0;
527     }
528    
529 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
530 sysadm 1.1 {
531 sysadm 1.4 static int display_nickname = 0;
532    
533 sysadm 1.1 SECTION_LIST *p_section;
534 sysadm 1.46 int64_t section_index;
535     int32_t aid_location;
536 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
537     char master_list[(BBS_username_max_len + 1) * 3 + 1];
538 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
539 sysadm 1.1 ARTICLE *p_articles[BBS_article_limit_per_page];
540     int article_count;
541 sysadm 1.6 int page_count;
542 sysadm 1.36 int ontop_start_offset;
543 sysadm 1.1 int page_id = 0;
544     int selected_index = 0;
545 sysadm 1.10 ARTICLE_CACHE cache;
546 sysadm 1.1 int ret;
547 sysadm 1.12 int loop;
548     int direction;
549 sysadm 1.24 ARTICLE article_new;
550 sysadm 1.31 int page_id_cur;
551 sysadm 1.46 const ARTICLE *p_article_locate;
552 sysadm 1.1
553 sysadm 1.50 p_section = section_list_find_by_name(sname);
554 sysadm 1.1 if (p_section == NULL)
555     {
556     log_error("Section %s not found\n", sname);
557     return -1;
558     }
559    
560 sysadm 1.52 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
561     {
562     log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
563     p_section->sid, BBS_priv.uid);
564     return -1;
565     }
566    
567 sysadm 1.50 section_index = get_section_index(p_section);
568    
569 sysadm 1.5 if ((ret = section_list_rd_lock(p_section)) < 0)
570     {
571     log_error("section_list_rd_lock(sid = 0) error\n");
572     return -2;
573     }
574    
575     strncpy(stitle, p_section->stitle, sizeof(stitle) - 1);
576     stitle[sizeof(stitle) - 1] = '\0';
577     strncpy(master_list, p_section->master_list, sizeof(master_list) - 1);
578     master_list[sizeof(master_list) - 1] = '\0';
579    
580     if ((ret = section_list_rd_unlock(p_section)) < 0)
581     {
582     log_error("section_list_rd_unlock(sid = 0) error\n");
583     return -2;
584     }
585    
586 sysadm 1.46 if (aid == 0)
587     {
588     aid_location = section_aid_locations[section_index];
589     }
590     else
591     {
592     aid_location = aid;
593 sysadm 1.51 }
594 sysadm 1.46
595     // Locate at article with aid_locate
596     if (aid_location > 0)
597     {
598     p_article_locate = article_block_find_by_aid(aid_location);
599     if (p_article_locate == NULL)
600     {
601     log_error("article_block_find_by_aid(%d) error\n", aid_location);
602     return -3;
603     }
604    
605     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
606     &page_id, &selected_index, &article_count);
607     if (ret < 0)
608     {
609     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
610     p_section->sid, p_article_locate->aid);
611     return -3;
612     }
613     }
614    
615 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
616 sysadm 1.1 {
617     log_error("section_list_draw_screen() error\n");
618     return -2;
619     }
620    
621 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
622 sysadm 1.5 if (ret < 0)
623 sysadm 1.1 {
624 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
625     return -3;
626 sysadm 1.1 }
627 sysadm 1.5
628 sysadm 1.46 section_topic_view_tid = -1;
629    
630 sysadm 1.5 if (article_count == 0) // empty section
631 sysadm 1.1 {
632     selected_index = 0;
633     }
634 sysadm 1.46 else if (aid > 0)
635     {
636     // Update current topic
637     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
638    
639     // Update current aid location
640     section_aid_locations[section_index] = p_articles[selected_index]->aid;
641     }
642 sysadm 1.1
643     while (!SYS_server_exit)
644     {
645 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
646 sysadm 1.1 if (ret < 0)
647     {
648     log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
649     return -4;
650     }
651 sysadm 1.6
652 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
653 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
654 sysadm 1.7 page_id + 1, MAX(page_count, 1));
655 sysadm 1.8
656 sysadm 1.6 show_bottom(page_info_str);
657 sysadm 1.1 iflush();
658    
659 sysadm 1.33 if (user_online_update(sname) < 0)
660     {
661     log_error("user_online_update(%s) error\n", sname);
662     }
663    
664 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
665 sysadm 1.1 switch (ret)
666     {
667     case EXIT_SECTION:
668     return 0;
669     case CHANGE_PAGE:
670 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
671 sysadm 1.5 if (ret < 0)
672 sysadm 1.1 {
673 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
674     return -3;
675 sysadm 1.1 }
676 sysadm 1.5 if (article_count == 0) // empty section
677 sysadm 1.1 {
678     selected_index = 0;
679     }
680 sysadm 1.5 else if (selected_index >= article_count)
681 sysadm 1.1 {
682     selected_index = article_count - 1;
683     }
684     break;
685     case VIEW_ARTICLE:
686 sysadm 1.12 do
687 sysadm 1.9 {
688 sysadm 1.12 loop = 0;
689 sysadm 1.9
690 sysadm 1.12 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
691     {
692     log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
693     break;
694     }
695    
696 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
697     {
698     log_error("user_online_update(VIEW_ARTICLE) error\n");
699     }
700    
701 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
702 sysadm 1.12 display_article_key_handler, DATA_READ_HELP);
703    
704     if (article_cache_unload(&cache) < 0)
705     {
706     log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
707     break;
708     }
709    
710 sysadm 1.17 // Update article_view_log
711     if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
712     {
713     log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
714     }
715    
716 sysadm 1.12 switch (ret)
717     {
718     case KEY_UP:
719     if (selected_index <= 0)
720     {
721     if (page_id > 0)
722     {
723     page_id--;
724     selected_index = BBS_article_limit_per_page - 1;
725    
726 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
727 sysadm 1.12 if (ret < 0)
728     {
729     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
730     return -3;
731     }
732    
733     if (article_count != BBS_article_limit_per_page) // page is not full
734     {
735     selected_index = MAX(0, article_count - 1);
736     }
737     else
738     {
739     loop = 1;
740     }
741     }
742     }
743     else
744     {
745     selected_index--;
746     loop = 1;
747     }
748     break;
749     case KEY_DOWN:
750     if (selected_index + 1 >= article_count) // next page
751     {
752     if (page_id + 1 < page_count)
753     {
754     page_id++;
755     selected_index = 0;
756    
757 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
758 sysadm 1.12 if (ret < 0)
759     {
760     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
761     return -3;
762     }
763    
764     if (article_count == 0) // empty page
765     {
766     selected_index = 0;
767     }
768     else
769     {
770     loop = 1;
771     }
772     }
773     }
774     else
775     {
776     selected_index++;
777     loop = 1;
778     }
779     break;
780     case KEY_PGUP:
781     case KEY_PGDN:
782     direction = (ret == KEY_PGUP ? -1 : 1);
783 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
784     &page_id, &selected_index, &article_count);
785 sysadm 1.12 if (ret < 0)
786     {
787 sysadm 1.31 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
788 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
789     return -3;
790     }
791 sysadm 1.31 else if (ret > 0) // found
792 sysadm 1.12 {
793 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
794 sysadm 1.12 if (ret < 0)
795     {
796     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
797     return -3;
798     }
799     loop = 1;
800     }
801     break;
802 sysadm 1.20 case 'r': // Reply article
803 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
804     {
805     log_error("user_online_update(REPLY_ARTICLE) error\n");
806     }
807    
808 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
809 sysadm 1.20 {
810 sysadm 1.33 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
811 sysadm 1.20 }
812     loop = 1;
813     break;
814 sysadm 1.31 case '=': // First topic article
815     case '\\': // Last topic article
816     page_id_cur = page_id;
817     direction = (ret == '=' ? -1 : 1);
818     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
819     &page_id, &selected_index, &article_count);
820     if (ret < 0)
821     {
822     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
823     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
824     return -3;
825     }
826     else if (ret > 0) // found
827     {
828     if (page_id != page_id_cur) // page changed
829     {
830 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
831 sysadm 1.31 if (ret < 0)
832     {
833     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
834     return -3;
835     }
836     }
837     loop = 1;
838     }
839     break;
840 sysadm 1.12 }
841     } while (loop);
842 sysadm 1.13
843     // Update current topic
844     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
845 sysadm 1.46
846     // Update current aid location
847     section_aid_locations[section_index] = p_articles[selected_index]->aid;
848 sysadm 1.35
849     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
850     {
851     log_error("section_list_draw_screen() error\n");
852     return -2;
853     }
854     break;
855 sysadm 1.4 case CHANGE_NAME_DISPLAY:
856     display_nickname = !display_nickname;
857 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
858 sysadm 1.1 {
859     log_error("section_list_draw_screen() error\n");
860     return -2;
861     }
862     break;
863 sysadm 1.20 case POST_ARTICLE:
864 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
865     {
866     log_error("user_online_update(POST_ARTICLE) error\n");
867     }
868    
869 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
870 sysadm 1.20 {
871 sysadm 1.26 log_error("article_post(sid=%d) error\n", p_section->sid);
872 sysadm 1.20 }
873 sysadm 1.24 else if (ret > 0) // New article posted
874     {
875 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
876 sysadm 1.24 if (ret < 0)
877     {
878     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
879     return -3;
880     }
881     }
882 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
883     {
884     log_error("section_list_draw_screen() error\n");
885     return -2;
886     }
887     break;
888     case EDIT_ARTICLE:
889 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
890     p_articles[selected_index]->uid != BBS_priv.uid)
891 sysadm 1.20 {
892 sysadm 1.26 break; // No permission
893 sysadm 1.20 }
894 sysadm 1.33
895     if (user_online_update("EDIT_ARTICLE") < 0)
896     {
897     log_error("user_online_update() error\n");
898     }
899    
900 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
901 sysadm 1.20 {
902 sysadm 1.26 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
903     }
904     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
905     {
906     log_error("section_list_draw_screen() error\n");
907     return -2;
908     }
909     break;
910     case DELETE_ARTICLE:
911     if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
912     (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
913     {
914     break; // No permission
915     }
916 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
917 sysadm 1.26 {
918     log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
919 sysadm 1.20 }
920 sysadm 1.30 else if (ret > 0) // Article deleted
921     {
922 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
923 sysadm 1.30 if (ret < 0)
924     {
925     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
926     return -3;
927     }
928     }
929 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
930     {
931     log_error("section_list_draw_screen() error\n");
932     return -2;
933     }
934     break;
935 sysadm 1.41 case QUERY_ARTICLE:
936     if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
937     {
938     log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
939     }
940     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
941     {
942     log_error("section_list_draw_screen() error\n");
943     return -2;
944     }
945     break;
946 sysadm 1.53 case SET_FAVOR_ARTICLE:
947     ret = article_favor_set(p_articles[selected_index]->tid == 0
948     ? p_articles[selected_index]->aid
949     : p_articles[selected_index]->tid,
950     &BBS_article_favor, 1);
951     if (ret < 0)
952     {
953     log_error("article_favor_set(aid=%d, 1) error\n",
954     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
955     }
956     break;
957     case UNSET_FAVOR_ARTICLE:
958     ret = article_favor_set(p_articles[selected_index]->tid == 0
959     ? p_articles[selected_index]->aid
960     : p_articles[selected_index]->tid,
961     &BBS_article_favor, 0);
962     if (ret < 0)
963     {
964     log_error("article_favor_set(aid=%d, 0) error\n",
965     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
966     }
967     break;
968 sysadm 1.31 case FIRST_TOPIC_ARTICLE:
969     case LAST_TOPIC_ARTICLE:
970     page_id_cur = page_id;
971     direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
972     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
973     &page_id, &selected_index, &article_count);
974     if (ret < 0)
975     {
976     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
977     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
978     return -3;
979     }
980     else if (ret > 0 && page_id != page_id_cur) // found and page changed
981     {
982 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
983 sysadm 1.31 if (ret < 0)
984     {
985     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
986     return -3;
987     }
988     }
989     break;
990 sysadm 1.45 case SCAN_NEW_ARTICLE:
991 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
992 sysadm 1.45 if (ret < 0)
993     {
994     log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
995     p_section->sid, p_articles[selected_index]->aid);
996     return -3;
997     }
998     else if (ret == 0) // not found
999     {
1000     break;
1001     }
1002     page_id_cur = page_id;
1003 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1004 sysadm 1.45 &page_id, &selected_index, &article_count);
1005     if (ret < 0)
1006     {
1007     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1008 sysadm 1.46 p_section->sid, p_article_locate->aid);
1009 sysadm 1.45 return -3;
1010     }
1011     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1012     {
1013     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1014     if (ret < 0)
1015     {
1016     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1017     return -3;
1018     }
1019     }
1020     break;
1021 sysadm 1.28 case SHOW_HELP:
1022     // Display help information
1023     display_file(DATA_READ_HELP, 1);
1024     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1025     {
1026     log_error("section_list_draw_screen() error\n");
1027     return -2;
1028     }
1029     break;
1030 sysadm 1.37 case VIEW_EX_DIR:
1031     if (section_list_ex_dir_display(p_section) < 0)
1032     {
1033     log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
1034     }
1035     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1036     {
1037     log_error("section_list_draw_screen() error\n");
1038     return -2;
1039     }
1040     break;
1041 sysadm 1.48 case SHOW_TOP10:
1042     show_top10_menu(NULL);
1043     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1044     {
1045     log_error("section_list_draw_screen() error\n");
1046     return -2;
1047     }
1048     break;
1049 sysadm 1.1 default:
1050     log_error("Unknown command %d\n", ret);
1051     }
1052     }
1053    
1054     return 0;
1055     }
1056 sysadm 1.37
1057     int section_list_ex_dir_display(SECTION_LIST *p_section)
1058     {
1059     MENU_SET ex_menu_set;
1060     int ch = 0;
1061    
1062     if (p_section == NULL)
1063     {
1064     log_error("NULL pointer error\n");
1065     return -1;
1066     }
1067    
1068 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1069     {
1070     moveto(2, 1);
1071     clrtoeol();
1072 sysadm 1.40 prints("该版块精华区未开放");
1073 sysadm 1.39 press_any_key();
1074     return 0;
1075     }
1076    
1077 sysadm 1.37 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1078     {
1079     log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1080     return -3;
1081     }
1082     if (get_menu_shm_readonly(&ex_menu_set) < 0)
1083     {
1084 sysadm 1.39 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1085 sysadm 1.37 return -3;
1086     }
1087    
1088     clearscr();
1089 sysadm 1.38 show_bottom("");
1090 sysadm 1.37
1091     if (display_menu(&ex_menu_set) == 0)
1092     {
1093     while (!SYS_server_exit)
1094     {
1095     iflush();
1096     ch = igetch(100);
1097 sysadm 1.54
1098     if (ch != KEY_NULL && ch != KEY_TIMEOUT)
1099     {
1100     BBS_last_access_tm = time(NULL);
1101     }
1102    
1103 sysadm 1.37 switch (ch)
1104     {
1105     case KEY_NULL: // broken pipe
1106 sysadm 1.54 log_error("KEY_NULL\n");
1107 sysadm 1.37 return 0;
1108     case KEY_TIMEOUT:
1109     if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
1110     {
1111 sysadm 1.54 log_error("User input timeout\n");
1112 sysadm 1.37 return 0;
1113     }
1114     continue;
1115     case CR:
1116     default:
1117     switch (menu_control(&ex_menu_set, ch))
1118     {
1119     case EXITMENU:
1120     ch = EXITMENU;
1121     break;
1122     case REDRAW:
1123     clearscr();
1124 sysadm 1.38 show_bottom("");
1125 sysadm 1.37 display_menu(&ex_menu_set);
1126     break;
1127     case NOREDRAW:
1128     case UNKNOWN_CMD:
1129     default:
1130     break;
1131     }
1132     }
1133    
1134     if (ch == EXITMENU)
1135     {
1136     break;
1137     }
1138     }
1139     }
1140    
1141     detach_menu_shm(&ex_menu_set);
1142    
1143     return 0;
1144     }

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