/[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.57 - (hide annotations)
Sat Oct 25 13:09:42 2025 UTC (4 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.56: +33 -1 lines
Content type: text/x-csrc
Press Ctrl-A in section list to display user information of selected article

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

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