/[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.68 - (hide annotations)
Tue Nov 4 06:36:52 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.67: +56 -1 lines
Content type: text/x-csrc
Locate at the last visible article of the section by pressing END at the bottom of section article list.
When exiting the section, set the last selected article to the last visible article if the selected one was pinned.

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.63 #include "user_list_display.h"
35 sysadm 1.18 #include "user_priv.h"
36 sysadm 1.65 #include <ctype.h>
37 sysadm 1.59 #include <errno.h>
38 sysadm 1.29 #include <string.h>
39 sysadm 1.1 #include <time.h>
40 sysadm 1.6 #include <sys/param.h>
41 sysadm 1.1
42 sysadm 1.66 #define TITLE_SEARCH_MAX_LEN 60
43    
44 sysadm 1.59 static int32_t section_aid_locations[BBS_max_section] = {0};
45 sysadm 1.11 static int section_topic_view_mode = 0;
46 sysadm 1.13 static int section_topic_view_tid = -1;
47 sysadm 1.11
48 sysadm 1.1 enum select_cmd_t
49     {
50     EXIT_SECTION = 0,
51 sysadm 1.41 VIEW_ARTICLE,
52     CHANGE_PAGE,
53     SHOW_HELP,
54     CHANGE_NAME_DISPLAY,
55     POST_ARTICLE,
56     EDIT_ARTICLE,
57     DELETE_ARTICLE,
58     QUERY_ARTICLE,
59 sysadm 1.57 QUERY_USER,
60 sysadm 1.53 SET_FAVOR_ARTICLE,
61     UNSET_FAVOR_ARTICLE,
62 sysadm 1.41 FIRST_TOPIC_ARTICLE,
63     LAST_TOPIC_ARTICLE,
64 sysadm 1.68 LAST_SECTION_ARTICLE,
65 sysadm 1.45 SCAN_NEW_ARTICLE,
66 sysadm 1.64 SCAN_ARTICLE_BACKWARD_BY_USER,
67     SCAN_ARTICLE_FORWARD_BY_USER,
68 sysadm 1.66 SCAN_ARTICLE_BACKWARD_BY_TITLE,
69     SCAN_ARTICLE_FORWARD_BY_TITLE,
70 sysadm 1.41 VIEW_EX_DIR,
71 sysadm 1.48 SHOW_TOP10,
72 sysadm 1.63 SEARCH_USER,
73 sysadm 1.1 };
74    
75 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)
76 sysadm 1.1 {
77     char str_time[LINE_BUFFER_LEN];
78     struct tm tm_sub;
79     char title_f[BBS_article_title_max_len + 1];
80     int title_f_len;
81     int eol;
82     int len;
83     int i;
84 sysadm 1.42 size_t j;
85 sysadm 1.3 char article_flag;
86 sysadm 1.17 int is_viewed;
87 sysadm 1.53 int is_favor;
88 sysadm 1.3 time_t tm_now;
89    
90     time(&tm_now);
91 sysadm 1.1
92     clrline(4, 23);
93    
94     for (i = 0; i < article_count; i++)
95     {
96 sysadm 1.18 if (p_articles[i]->uid == BBS_priv.uid)
97 sysadm 1.17 {
98 sysadm 1.18 is_viewed = 1;
99     }
100     else
101     {
102     is_viewed = article_view_log_is_viewed(p_articles[i]->aid, &BBS_article_view_log);
103     if (is_viewed < 0)
104     {
105     log_error("article_view_log_is_viewed(aid=%d) error\n", p_articles[i]->aid);
106     is_viewed = 0;
107     }
108 sysadm 1.17 }
109    
110 sysadm 1.53 if (p_articles[i]->tid == 0)
111     {
112     is_favor = article_favor_check(p_articles[i]->aid, &BBS_article_favor);
113     if (is_favor < 0)
114     {
115     log_error("article_favor_check(aid=%d) error\n", p_articles[i]->aid);
116     is_favor = 0;
117     }
118     }
119     else
120     {
121     is_favor = 0;
122     }
123    
124 sysadm 1.3 if (p_articles[i]->excerption)
125     {
126 sysadm 1.17 article_flag = (is_viewed ? 'm' : 'M');
127 sysadm 1.3 }
128 sysadm 1.17 else if (p_articles[i]->lock && is_viewed)
129 sysadm 1.3 {
130     article_flag = 'x';
131     }
132 sysadm 1.35 else
133     {
134     article_flag = (is_viewed ? ' ' : 'N');
135     }
136 sysadm 1.3
137 sysadm 1.1 localtime_r(&p_articles[i]->sub_dt, &tm_sub);
138 sysadm 1.3 if (tm_now - p_articles[i]->sub_dt < 3600 * 24 * 365)
139     {
140     strftime(str_time, sizeof(str_time), "%b %e ", &tm_sub);
141     }
142     else
143     {
144     strftime(str_time, sizeof(str_time), "%m/%Y", &tm_sub);
145     }
146    
147 sysadm 1.40 strncpy(title_f, (p_articles[i]->tid == 0 ? "● " : ""), sizeof(title_f) - 1);
148 sysadm 1.1 title_f[sizeof(title_f) - 1] = '\0';
149 sysadm 1.40 strncat(title_f, (p_articles[i]->transship ? "[转载]" : ""), sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
150 sysadm 1.42
151     // Rewrite title with "Re: Re: " prefix into "Re: ... "
152     j = 0;
153     if (p_articles[i]->tid != 0)
154     {
155     while (strncmp(p_articles[i]->title + j, "Re: ", strlen("Re: ")) == 0)
156     {
157     j += strlen("Re: ");
158     }
159     if (j >= strlen("Re: Re: "))
160     {
161     strncat(title_f, "Re: ... ", sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
162     }
163     else
164     {
165     j = 0;
166     }
167     }
168     strncat(title_f, p_articles[i]->title + j, sizeof(title_f) - 1 - strnlen(title_f, sizeof(title_f)));
169    
170 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);
171 sysadm 1.1 if (title_f[len] != '\0')
172     {
173     title_f[len] = '\0';
174     }
175    
176     moveto(4 + i, 1);
177 sysadm 1.36 if (i >= ontop_start_offset)
178     {
179 sysadm 1.53 prints(" \033[1;33m[提示]\033[m%c%c %s%*s %s %s%s\033[m",
180     (is_favor ? '@' : ' '),
181 sysadm 1.36 article_flag,
182     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
183 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
184     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
185 sysadm 1.36 "",
186     str_time,
187     (p_articles[i]->aid == section_topic_view_tid
188     ? "\033[1;33m"
189     : (p_articles[i]->tid == section_topic_view_tid
190     ? "\033[1;36m"
191     : "")),
192     title_f);
193     }
194     else
195     {
196 sysadm 1.53 prints(" %s%7d\033[m%c%c %s%*s %s %s%s\033[m",
197 sysadm 1.36 (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     p_articles[i]->aid,
203 sysadm 1.53 (is_favor ? '@' : ' '),
204 sysadm 1.36 article_flag,
205     (display_nickname ? p_articles[i]->nickname : p_articles[i]->username),
206 sysadm 1.43 (display_nickname ? BBS_nickname_max_len / 2 - str_length(p_articles[i]->nickname, 1)
207     : BBS_username_max_len - str_length(p_articles[i]->username, 1)),
208 sysadm 1.36 "",
209     str_time,
210     (p_articles[i]->aid == section_topic_view_tid
211     ? "\033[1;33m"
212     : (p_articles[i]->tid == section_topic_view_tid
213     ? "\033[1;36m"
214     : "")),
215     title_f);
216     }
217 sysadm 1.1 }
218    
219     return 0;
220     }
221    
222 sysadm 1.5 static int section_list_draw_screen(const char *sname, const char *stitle, const char *master_list, int display_nickname)
223 sysadm 1.1 {
224 sysadm 1.40 char str_section_master[LINE_BUFFER_LEN] = "诚征版主中";
225 sysadm 1.1 char str_section_name[LINE_BUFFER_LEN];
226    
227 sysadm 1.5 if (master_list[0] != '\0')
228 sysadm 1.1 {
229 sysadm 1.40 snprintf(str_section_master, sizeof(str_section_master), "版主:%s", master_list);
230 sysadm 1.1 }
231 sysadm 1.40 snprintf(str_section_name, sizeof(str_section_name), "讨论区 [%s]", sname);
232 sysadm 1.1
233     clearscr();
234 sysadm 1.5 show_top(str_section_master, stitle, str_section_name);
235 sysadm 1.1 moveto(2, 0);
236 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] "
237     "阅读[\033[1;32m→\033[0;37m,\033[1;32mENTER\033[0;37m] 发表[\033[1;32mCtrl-P\033[0;37m] "
238     "%s[\033[1;32mn\033[0;37m] 精华区[\033[1;32mx\033[0;37m] 帮助[\033[1;32mh\033[0;37m]\033[m",
239     (display_nickname ? "用户名" : "昵称"));
240 sysadm 1.1 moveto(3, 0);
241 sysadm 1.4 if (display_nickname)
242     {
243 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发布者昵称 日 期 文章标题 \033[m");
244 sysadm 1.4 }
245     else
246     {
247 sysadm 1.40 prints("\033[44;37m \033[1;37m 编 号 发 布 者 日 期 文章标题 \033[m");
248 sysadm 1.4 }
249 sysadm 1.1
250     return 0;
251     }
252    
253     static enum select_cmd_t section_list_select(int total_page, int item_count, int *p_page_id, int *p_selected_index)
254     {
255     int old_page_id = *p_page_id;
256     int old_selected_index = *p_selected_index;
257     int ch;
258 sysadm 1.30 time_t last_refresh_tm = time(NULL);
259 sysadm 1.1
260     if (item_count > 0 && *p_selected_index >= 0)
261     {
262     moveto(4 + *p_selected_index, 1);
263     outc('>');
264     iflush();
265     }
266    
267     while (!SYS_server_exit)
268     {
269     ch = igetch(100);
270    
271 sysadm 1.54 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
272     {
273     BBS_last_access_tm = time(NULL);
274     }
275    
276 sysadm 1.1 switch (ch)
277     {
278 sysadm 1.57 case KEY_NULL: // broken pipe
279 sysadm 1.54 log_error("KEY_NULL\n");
280     return EXIT_SECTION;
281 sysadm 1.1 case KEY_TIMEOUT:
282 sysadm 1.30 if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
283 sysadm 1.1 {
284 sysadm 1.54 log_error("User input timeout\n");
285     return EXIT_SECTION;
286 sysadm 1.1 }
287     continue;
288 sysadm 1.54 case KEY_ESC:
289     case KEY_LEFT:
290     return EXIT_SECTION;
291 sysadm 1.4 case 'n':
292     return CHANGE_NAME_DISPLAY;
293 sysadm 1.1 case CR:
294 sysadm 1.28 case 'r':
295 sysadm 1.1 case KEY_RIGHT:
296     if (item_count > 0)
297     {
298     return VIEW_ARTICLE;
299     }
300     break;
301 sysadm 1.20 case Ctrl('P'):
302     return POST_ARTICLE;
303     case 'E':
304 sysadm 1.41 if (item_count > 0)
305     {
306     return EDIT_ARTICLE;
307     }
308     break;
309 sysadm 1.26 case 'd':
310 sysadm 1.41 if (item_count > 0)
311     {
312     return DELETE_ARTICLE;
313     }
314     break;
315     case Ctrl('Q'):
316     if (item_count > 0)
317     {
318     return QUERY_ARTICLE;
319     }
320     break;
321 sysadm 1.57 case Ctrl('A'):
322     if (item_count > 0)
323     {
324     return QUERY_USER;
325     }
326     break;
327 sysadm 1.53 case 'F':
328     if (item_count > 0)
329     {
330     return SET_FAVOR_ARTICLE;
331     }
332     break;
333     case '-':
334     if (item_count > 0)
335     {
336     return UNSET_FAVOR_ARTICLE;
337     }
338     break;
339 sysadm 1.1 case KEY_HOME:
340     *p_page_id = 0;
341 sysadm 1.28 case 'P':
342 sysadm 1.1 case KEY_PGUP:
343     *p_selected_index = 0;
344 sysadm 1.28 case 'k':
345 sysadm 1.1 case KEY_UP:
346     if (*p_selected_index <= 0)
347     {
348     if (*p_page_id > 0)
349     {
350     (*p_page_id)--;
351     *p_selected_index = BBS_article_limit_per_page - 1;
352     }
353 sysadm 1.44 else if (ch == KEY_UP || ch == 'k') // Rotate to the tail of section list
354     {
355     if (total_page > 0)
356     {
357     *p_page_id = total_page - 1;
358     }
359     if (item_count > 0)
360     {
361     *p_selected_index = item_count - 1;
362     }
363     }
364 sysadm 1.1 }
365     else
366     {
367     (*p_selected_index)--;
368     }
369     break;
370 sysadm 1.28 case '$':
371 sysadm 1.1 case KEY_END:
372 sysadm 1.68 if (*p_page_id + 1 == total_page && *p_selected_index + 1 == item_count) // Press END at end of list
373     {
374     return LAST_SECTION_ARTICLE;
375     }
376 sysadm 1.1 if (total_page > 0)
377     {
378     *p_page_id = total_page - 1;
379     }
380 sysadm 1.28 case 'N':
381 sysadm 1.1 case KEY_PGDN:
382     if (item_count > 0)
383     {
384     *p_selected_index = item_count - 1;
385     }
386 sysadm 1.28 case 'j':
387 sysadm 1.1 case KEY_DOWN:
388     if (*p_selected_index + 1 >= item_count) // next page
389     {
390     if (*p_page_id + 1 < total_page)
391     {
392     (*p_page_id)++;
393     *p_selected_index = 0;
394     }
395 sysadm 1.44 else if (ch == KEY_DOWN || ch == 'j') // Rotate to the head of section list
396 sysadm 1.25 {
397 sysadm 1.44 *p_page_id = 0;
398     *p_selected_index = 0;
399 sysadm 1.25 }
400 sysadm 1.1 }
401     else
402     {
403     (*p_selected_index)++;
404     }
405     break;
406 sysadm 1.31 case '=':
407 sysadm 1.41 if (item_count > 0)
408     {
409     return FIRST_TOPIC_ARTICLE;
410     }
411     break;
412 sysadm 1.31 case '\\':
413 sysadm 1.41 if (item_count > 0)
414     {
415     return LAST_TOPIC_ARTICLE;
416     }
417     break;
418 sysadm 1.45 case 'S':
419     if (item_count > 0)
420     {
421     return SCAN_NEW_ARTICLE;
422     }
423     break;
424 sysadm 1.64 case 'A':
425     if (item_count > 0)
426     {
427     return SCAN_ARTICLE_BACKWARD_BY_USER;
428     }
429     break;
430     case 'a':
431     if (item_count > 0)
432     {
433     return SCAN_ARTICLE_FORWARD_BY_USER;
434     }
435     break;
436 sysadm 1.66 case '?':
437     if (item_count > 0)
438     {
439     return SCAN_ARTICLE_BACKWARD_BY_TITLE;
440     }
441     break;
442     case '/':
443     if (item_count > 0)
444     {
445     return SCAN_ARTICLE_FORWARD_BY_TITLE;
446     }
447     break;
448 sysadm 1.63 case 'u':
449     return SEARCH_USER;
450 sysadm 1.28 case 'h':
451     return SHOW_HELP;
452 sysadm 1.37 case 'x':
453     return VIEW_EX_DIR;
454 sysadm 1.49 case 'H':
455 sysadm 1.48 return SHOW_TOP10;
456 sysadm 1.1 default:
457 sysadm 1.56 break;
458 sysadm 1.1 }
459    
460     if (old_page_id != *p_page_id)
461     {
462     return CHANGE_PAGE;
463     }
464    
465     if (item_count > 0 && old_selected_index != *p_selected_index)
466     {
467     if (old_selected_index >= 0)
468     {
469     moveto(4 + old_selected_index, 1);
470     outc(' ');
471     }
472     if (*p_selected_index >= 0)
473     {
474     moveto(4 + *p_selected_index, 1);
475     outc('>');
476     }
477     iflush();
478    
479     old_selected_index = *p_selected_index;
480     }
481    
482 sysadm 1.30 if (BBS_last_access_tm - last_refresh_tm >= BBS_section_list_load_interval)
483     {
484     return CHANGE_PAGE; // force section list refresh
485     }
486 sysadm 1.1 }
487    
488     return EXIT_SECTION;
489     }
490    
491 sysadm 1.11 static int display_article_key_handler(int *p_key, DISPLAY_CTX *p_ctx)
492 sysadm 1.10 {
493 sysadm 1.11 switch (*p_key)
494 sysadm 1.10 {
495 sysadm 1.11 case 'p':
496 sysadm 1.28 case Ctrl('X'):
497 sysadm 1.11 section_topic_view_mode = !section_topic_view_mode;
498 sysadm 1.10 case 0: // Set msg
499 sysadm 1.11 if (section_topic_view_mode)
500 sysadm 1.10 {
501 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
502 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
503     "同主题阅读[\033[32m↑\033[33m/\033[32m↓\033[33m] "
504     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
505 sysadm 1.10 }
506     else
507     {
508 sysadm 1.11 snprintf(p_ctx->msg, sizeof(p_ctx->msg),
509 sysadm 1.40 "| 返回[\033[32m←\033[33m,\033[32mESC\033[33m] "
510     "移动[\033[32m↑\033[33m/\033[32m↓\033[33m/\033[32mPgUp\033[33m/\033[32mPgDn\033[33m] "
511     "切换[\033[32mp\033[33m] 回复[\033[32mr\033[33m] 帮助[\033[32mh\033[33m] |");
512 sysadm 1.10 }
513 sysadm 1.11 *p_key = 0;
514 sysadm 1.10 break;
515 sysadm 1.20 case 'r': // Reply article
516     return 1;
517 sysadm 1.31 case '=': // First topic article
518     return 1;
519     case '\\': // Last topic article
520     return 1;
521 sysadm 1.12 case KEY_UP:
522 sysadm 1.16 case KEY_PGUP:
523     case KEY_HOME:
524 sysadm 1.12 if (p_ctx->reach_begin)
525     {
526     if (section_topic_view_mode)
527     {
528     *p_key = KEY_PGUP;
529     }
530 sysadm 1.16 else
531     {
532     *p_key = KEY_UP;
533     }
534 sysadm 1.12 return 1;
535     }
536     break;
537 sysadm 1.28 case 'k':
538     if (section_topic_view_mode)
539     {
540     *p_key = KEY_PGUP;
541     }
542     else
543     {
544     *p_key = KEY_UP;
545     }
546     return 1;
547 sysadm 1.12 case KEY_DOWN:
548 sysadm 1.16 case KEY_PGDN:
549     case KEY_END:
550 sysadm 1.12 if (p_ctx->reach_end)
551     {
552     if (section_topic_view_mode)
553     {
554     *p_key = KEY_PGDN;
555     }
556 sysadm 1.16 else
557     {
558     *p_key = KEY_DOWN;
559     }
560 sysadm 1.12 return 1;
561     }
562     break;
563 sysadm 1.28 case 'j':
564     if (section_topic_view_mode)
565     {
566     *p_key = KEY_PGDN;
567     }
568     else
569     {
570     *p_key = KEY_DOWN;
571     }
572     return 1;
573 sysadm 1.10 }
574    
575     return 0;
576     }
577    
578 sysadm 1.46 int section_list_display(const char *sname, int32_t aid)
579 sysadm 1.1 {
580 sysadm 1.4 static int display_nickname = 0;
581    
582 sysadm 1.1 SECTION_LIST *p_section;
583 sysadm 1.46 int64_t section_index;
584     int32_t aid_location;
585 sysadm 1.5 char stitle[BBS_section_title_max_len + 1];
586     char master_list[(BBS_username_max_len + 1) * 3 + 1];
587 sysadm 1.6 char page_info_str[LINE_BUFFER_LEN];
588 sysadm 1.1 ARTICLE *p_articles[BBS_article_limit_per_page];
589     int article_count;
590 sysadm 1.6 int page_count;
591 sysadm 1.36 int ontop_start_offset;
592 sysadm 1.1 int page_id = 0;
593     int selected_index = 0;
594 sysadm 1.10 ARTICLE_CACHE cache;
595 sysadm 1.1 int ret;
596 sysadm 1.12 int loop;
597     int direction;
598 sysadm 1.24 ARTICLE article_new;
599 sysadm 1.31 int page_id_cur;
600 sysadm 1.46 const ARTICLE *p_article_locate;
601 sysadm 1.57 USER_INFO user_info;
602 sysadm 1.66 char user_intro[BBS_user_intro_max_len + 1];
603 sysadm 1.64 char username[BBS_username_max_len + 1];
604     char username_list[1][BBS_username_max_len + 1];
605     int32_t uid;
606     int i;
607     int ok;
608 sysadm 1.66 char title[BBS_article_title_max_len + 1] = "\0";
609 sysadm 1.1
610 sysadm 1.50 p_section = section_list_find_by_name(sname);
611 sysadm 1.1 if (p_section == NULL)
612     {
613     log_error("Section %s not found\n", sname);
614     return -1;
615     }
616    
617 sysadm 1.52 if (!checkpriv(&BBS_priv, p_section->sid, S_LIST))
618     {
619     log_error("Forbid access to unauthorized section, sid=%d, uid=%d\n",
620     p_section->sid, BBS_priv.uid);
621     return -1;
622     }
623    
624 sysadm 1.50 section_index = get_section_index(p_section);
625    
626 sysadm 1.58 if (get_section_info(p_section, NULL, stitle, master_list) < 0)
627 sysadm 1.5 {
628 sysadm 1.58 log_error("get_section_info(sid=%d) error\n", p_section->sid);
629     return -4;
630 sysadm 1.5 }
631    
632 sysadm 1.46 if (aid == 0)
633     {
634     aid_location = section_aid_locations[section_index];
635     }
636     else
637     {
638     aid_location = aid;
639 sysadm 1.51 }
640 sysadm 1.46
641     // Locate at article with aid_locate
642     if (aid_location > 0)
643     {
644     p_article_locate = article_block_find_by_aid(aid_location);
645     if (p_article_locate == NULL)
646     {
647     log_error("article_block_find_by_aid(%d) error\n", aid_location);
648     return -3;
649     }
650    
651     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
652     &page_id, &selected_index, &article_count);
653     if (ret < 0)
654     {
655     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
656     p_section->sid, p_article_locate->aid);
657     return -3;
658     }
659     }
660    
661 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
662 sysadm 1.1 {
663     log_error("section_list_draw_screen() error\n");
664     return -2;
665     }
666    
667 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
668 sysadm 1.5 if (ret < 0)
669 sysadm 1.1 {
670 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
671     return -3;
672 sysadm 1.1 }
673 sysadm 1.5
674 sysadm 1.46 section_topic_view_tid = -1;
675    
676 sysadm 1.5 if (article_count == 0) // empty section
677 sysadm 1.1 {
678     selected_index = 0;
679     }
680 sysadm 1.46 else if (aid > 0)
681     {
682     // Update current topic
683     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
684    
685     // Update current aid location
686     section_aid_locations[section_index] = p_articles[selected_index]->aid;
687     }
688 sysadm 1.1
689     while (!SYS_server_exit)
690     {
691 sysadm 1.36 ret = section_list_draw_items(page_id, p_articles, article_count, display_nickname, ontop_start_offset);
692 sysadm 1.1 if (ret < 0)
693     {
694     log_error("section_list_draw_items(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
695     return -4;
696     }
697 sysadm 1.6
698 sysadm 1.7 snprintf(page_info_str, sizeof(page_info_str),
699 sysadm 1.40 "\033[33m[第\033[36m%d\033[33m/\033[36m%d\033[33m页]",
700 sysadm 1.7 page_id + 1, MAX(page_count, 1));
701 sysadm 1.8
702 sysadm 1.6 show_bottom(page_info_str);
703 sysadm 1.1 iflush();
704    
705 sysadm 1.33 if (user_online_update(sname) < 0)
706     {
707     log_error("user_online_update(%s) error\n", sname);
708     }
709    
710 sysadm 1.6 ret = section_list_select(page_count, article_count, &page_id, &selected_index);
711 sysadm 1.60
712 sysadm 1.1 switch (ret)
713     {
714     case EXIT_SECTION:
715 sysadm 1.62 // Update current aid location
716     if (p_articles[selected_index] != NULL)
717     {
718 sysadm 1.68 if (selected_index >= ontop_start_offset)
719     {
720     ret = last_article_in_section(p_section, &p_article_locate);
721     if (ret < 0)
722     {
723     log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
724     return -3;
725     }
726     else if (ret == 0)
727     {
728     section_aid_locations[section_index] = 0;
729     }
730     else // ret > 0
731     {
732     section_aid_locations[section_index] = p_article_locate->aid;
733     }
734     }
735     else
736     {
737     section_aid_locations[section_index] = (p_articles[selected_index]->visible ? p_articles[selected_index]->aid : 0);
738     }
739 sysadm 1.62 }
740 sysadm 1.1 return 0;
741     case CHANGE_PAGE:
742 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
743 sysadm 1.5 if (ret < 0)
744 sysadm 1.1 {
745 sysadm 1.5 log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
746     return -3;
747 sysadm 1.1 }
748 sysadm 1.5 if (article_count == 0) // empty section
749 sysadm 1.1 {
750     selected_index = 0;
751     }
752 sysadm 1.5 else if (selected_index >= article_count)
753 sysadm 1.1 {
754     selected_index = article_count - 1;
755     }
756     break;
757     case VIEW_ARTICLE:
758 sysadm 1.12 do
759 sysadm 1.9 {
760 sysadm 1.12 loop = 0;
761 sysadm 1.9
762 sysadm 1.12 if (article_cache_load(&cache, VAR_ARTICLE_CACHE_DIR, p_articles[selected_index]) < 0)
763     {
764     log_error("article_cache_load(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
765     break;
766     }
767    
768 sysadm 1.33 if (user_online_update("VIEW_ARTICLE") < 0)
769     {
770     log_error("user_online_update(VIEW_ARTICLE) error\n");
771     }
772    
773 sysadm 1.19 ret = display_data(cache.p_data, cache.line_total, cache.line_offsets, 0,
774 sysadm 1.12 display_article_key_handler, DATA_READ_HELP);
775    
776     if (article_cache_unload(&cache) < 0)
777     {
778     log_error("article_cache_unload(aid=%d, cid=%d) error\n", p_articles[selected_index]->aid, p_articles[selected_index]->cid);
779     break;
780     }
781    
782 sysadm 1.17 // Update article_view_log
783     if (article_view_log_set_viewed(p_articles[selected_index]->aid, &BBS_article_view_log) < 0)
784     {
785     log_error("article_view_log_set_viewed(aid=%d) error\n", p_articles[selected_index]->aid);
786     }
787    
788 sysadm 1.12 switch (ret)
789     {
790     case KEY_UP:
791     if (selected_index <= 0)
792     {
793     if (page_id > 0)
794     {
795     page_id--;
796     selected_index = BBS_article_limit_per_page - 1;
797    
798 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
799 sysadm 1.12 if (ret < 0)
800     {
801     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
802     return -3;
803     }
804    
805     if (article_count != BBS_article_limit_per_page) // page is not full
806     {
807     selected_index = MAX(0, article_count - 1);
808     }
809     else
810     {
811     loop = 1;
812     }
813     }
814     }
815     else
816     {
817     selected_index--;
818     loop = 1;
819     }
820     break;
821     case KEY_DOWN:
822     if (selected_index + 1 >= article_count) // next page
823     {
824     if (page_id + 1 < page_count)
825     {
826     page_id++;
827     selected_index = 0;
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.12 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     if (article_count == 0) // empty page
837     {
838     selected_index = 0;
839     }
840     else
841     {
842     loop = 1;
843     }
844     }
845     }
846     else
847     {
848     selected_index++;
849     loop = 1;
850     }
851     break;
852     case KEY_PGUP:
853     case KEY_PGDN:
854     direction = (ret == KEY_PGUP ? -1 : 1);
855 sysadm 1.31 ret = locate_article_in_section(p_section, p_articles[selected_index], direction, 1,
856     &page_id, &selected_index, &article_count);
857 sysadm 1.12 if (ret < 0)
858     {
859 sysadm 1.31 log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=1) error\n",
860 sysadm 1.12 p_section->sid, p_articles[selected_index]->aid, direction);
861     return -3;
862     }
863 sysadm 1.31 else if (ret > 0) // found
864 sysadm 1.12 {
865 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
866 sysadm 1.12 if (ret < 0)
867     {
868     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
869     return -3;
870     }
871     loop = 1;
872     }
873     break;
874 sysadm 1.20 case 'r': // Reply article
875 sysadm 1.33 if (user_online_update("REPLY_ARTICLE") < 0)
876     {
877     log_error("user_online_update(REPLY_ARTICLE) error\n");
878     }
879    
880 sysadm 1.24 if (article_reply(p_section, p_articles[selected_index], &article_new) < 0)
881 sysadm 1.20 {
882 sysadm 1.33 log_error("article_reply(aid=%d) error\n", p_articles[selected_index]->aid);
883 sysadm 1.20 }
884 sysadm 1.67 else if (ret > 0) // Article replied
885     {
886     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
887     if (ret < 0)
888     {
889     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
890     return -3;
891     }
892     }
893 sysadm 1.20 loop = 1;
894     break;
895 sysadm 1.31 case '=': // First topic article
896     case '\\': // Last topic article
897     page_id_cur = page_id;
898     direction = (ret == '=' ? -1 : 1);
899     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
900     &page_id, &selected_index, &article_count);
901     if (ret < 0)
902     {
903     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
904     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
905     return -3;
906     }
907     else if (ret > 0) // found
908     {
909     if (page_id != page_id_cur) // page changed
910     {
911 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
912 sysadm 1.31 if (ret < 0)
913     {
914     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
915     return -3;
916     }
917     }
918     loop = 1;
919     }
920     break;
921 sysadm 1.12 }
922     } while (loop);
923 sysadm 1.13
924     // Update current topic
925     section_topic_view_tid = (p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
926 sysadm 1.46
927 sysadm 1.35 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
928     {
929     log_error("section_list_draw_screen() error\n");
930     return -2;
931     }
932     break;
933 sysadm 1.4 case CHANGE_NAME_DISPLAY:
934     display_nickname = !display_nickname;
935 sysadm 1.5 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
936 sysadm 1.1 {
937     log_error("section_list_draw_screen() error\n");
938     return -2;
939     }
940     break;
941 sysadm 1.20 case POST_ARTICLE:
942 sysadm 1.33 if (user_online_update("POST_ARTICLE") < 0)
943     {
944     log_error("user_online_update(POST_ARTICLE) error\n");
945     }
946    
947 sysadm 1.30 if ((ret = article_post(p_section, &article_new)) < 0)
948 sysadm 1.20 {
949 sysadm 1.26 log_error("article_post(sid=%d) error\n", p_section->sid);
950 sysadm 1.20 }
951 sysadm 1.24 else if (ret > 0) // New article posted
952     {
953 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
954 sysadm 1.24 if (ret < 0)
955     {
956 sysadm 1.67 log_error("query_section_articles(sid=%d, page_id=%d) error: %d\n", p_section->sid, page_id, ret);
957 sysadm 1.24 return -3;
958     }
959     }
960 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
961     {
962     log_error("section_list_draw_screen() error\n");
963     return -2;
964     }
965     break;
966     case EDIT_ARTICLE:
967 sysadm 1.26 if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
968     p_articles[selected_index]->uid != BBS_priv.uid)
969 sysadm 1.20 {
970 sysadm 1.26 break; // No permission
971 sysadm 1.20 }
972 sysadm 1.33
973     if (user_online_update("EDIT_ARTICLE") < 0)
974     {
975     log_error("user_online_update() error\n");
976     }
977    
978 sysadm 1.24 if (article_modify(p_section, p_articles[selected_index], &article_new) < 0)
979 sysadm 1.20 {
980 sysadm 1.26 log_error("article_modify(aid=%d) error\n", p_articles[selected_index]->aid);
981     }
982 sysadm 1.67 else if (ret > 0) // Article modified
983     {
984     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
985     if (ret < 0)
986     {
987     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
988     return -3;
989     }
990     }
991 sysadm 1.26 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
992     {
993     log_error("section_list_draw_screen() error\n");
994     return -2;
995     }
996     break;
997     case DELETE_ARTICLE:
998     if (!checkpriv(&BBS_priv, p_section->sid, S_POST) ||
999     (!checkpriv(&BBS_priv, p_section->sid, S_MAN_S) && p_articles[selected_index]->uid != BBS_priv.uid))
1000     {
1001     break; // No permission
1002     }
1003 sysadm 1.30 if ((ret = article_del(p_section, p_articles[selected_index])) < 0)
1004 sysadm 1.26 {
1005     log_error("article_del(aid=%d) error\n", p_articles[selected_index]->aid);
1006 sysadm 1.20 }
1007 sysadm 1.30 else if (ret > 0) // Article deleted
1008     {
1009 sysadm 1.67 do
1010 sysadm 1.30 {
1011 sysadm 1.67 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1012     if (ret >= 0 && selected_index > article_count - 1)
1013     {
1014     selected_index = article_count - 1;
1015     break;
1016     }
1017     else if (ret < 0 && page_id > 0)
1018     {
1019     page_id--;
1020     selected_index = BBS_article_limit_per_page - 1;
1021     }
1022     else if (ret < 0 && page_id <= 0)
1023     {
1024     selected_index = 0;
1025     break;
1026     }
1027     } while (ret < 0);
1028 sysadm 1.30 }
1029 sysadm 1.20 if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1030     {
1031     log_error("section_list_draw_screen() error\n");
1032     return -2;
1033     }
1034     break;
1035 sysadm 1.41 case QUERY_ARTICLE:
1036     if ((ret = display_article_meta(p_articles[selected_index]->aid)) < 0)
1037     {
1038     log_error("display_article_meta(aid=%d) error\n", p_articles[selected_index]->aid);
1039     }
1040     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1041     {
1042     log_error("section_list_draw_screen() error\n");
1043     return -2;
1044     }
1045     break;
1046 sysadm 1.57 case QUERY_USER:
1047 sysadm 1.61 if ((ret = query_user_info_by_uid(p_articles[selected_index]->uid, &user_info, user_intro, sizeof(user_intro))) < 0)
1048 sysadm 1.57 {
1049     log_error("query_user_info_by_uid(uid=%d) error\n", p_articles[selected_index]->uid);
1050     return -2;
1051     }
1052     else if (ret == 0)
1053     {
1054     clearscr();
1055     prints("该用户已升天");
1056     press_any_key();
1057     }
1058     else if (user_info_display(&user_info) < 0) // && ret > 0
1059     {
1060     log_error("user_info_display(uid=%d) error\n", p_articles[selected_index]->uid);
1061     }
1062    
1063     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1064     {
1065     log_error("section_list_draw_screen() error\n");
1066     return -2;
1067     }
1068     break;
1069 sysadm 1.53 case SET_FAVOR_ARTICLE:
1070     ret = article_favor_set(p_articles[selected_index]->tid == 0
1071     ? p_articles[selected_index]->aid
1072     : p_articles[selected_index]->tid,
1073     &BBS_article_favor, 1);
1074     if (ret < 0)
1075     {
1076     log_error("article_favor_set(aid=%d, 1) error\n",
1077     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1078     }
1079     break;
1080     case UNSET_FAVOR_ARTICLE:
1081     ret = article_favor_set(p_articles[selected_index]->tid == 0
1082     ? p_articles[selected_index]->aid
1083     : p_articles[selected_index]->tid,
1084     &BBS_article_favor, 0);
1085     if (ret < 0)
1086     {
1087     log_error("article_favor_set(aid=%d, 0) error\n",
1088     p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid);
1089     }
1090     break;
1091 sysadm 1.31 case FIRST_TOPIC_ARTICLE:
1092     case LAST_TOPIC_ARTICLE:
1093     page_id_cur = page_id;
1094     direction = (ret == FIRST_TOPIC_ARTICLE ? -1 : 1);
1095     ret = locate_article_in_section(p_section, p_articles[selected_index], direction, BBS_article_limit_per_section,
1096     &page_id, &selected_index, &article_count);
1097     if (ret < 0)
1098     {
1099     log_error("locate_article_in_section(sid=%d, aid=%d, direction=%d, step=%d) error\n",
1100     p_section->sid, p_articles[selected_index]->aid, direction, BBS_article_limit_per_section);
1101     return -3;
1102     }
1103     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1104     {
1105 sysadm 1.36 ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1106 sysadm 1.31 if (ret < 0)
1107     {
1108     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1109     return -3;
1110     }
1111     }
1112     break;
1113 sysadm 1.68 case LAST_SECTION_ARTICLE:
1114     page_id_cur = page_id;
1115     ret = last_article_in_section(p_section, &p_article_locate);
1116     if (ret < 0)
1117     {
1118     log_error("last_article_in_section(sid=%d) error\n", p_section->sid);
1119     return -3;
1120     }
1121     else if (ret == 0)
1122     {
1123     break;
1124     }
1125     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1126     &page_id, &selected_index, &article_count);
1127     if (ret < 0)
1128     {
1129     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1130     p_section->sid, p_article_locate->aid);
1131     return -3;
1132     }
1133     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1134     {
1135     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1136     if (ret < 0)
1137     {
1138     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1139     return -3;
1140     }
1141     }
1142     break;
1143 sysadm 1.45 case SCAN_NEW_ARTICLE:
1144 sysadm 1.46 ret = scan_unread_article_in_section(p_section, p_articles[selected_index], &p_article_locate);
1145 sysadm 1.45 if (ret < 0)
1146     {
1147     log_error("scan_unread_article_in_section(sid=%d, aid=%d) error\n",
1148     p_section->sid, p_articles[selected_index]->aid);
1149     return -3;
1150     }
1151     else if (ret == 0) // not found
1152     {
1153     break;
1154     }
1155     page_id_cur = page_id;
1156 sysadm 1.46 ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1157 sysadm 1.45 &page_id, &selected_index, &article_count);
1158     if (ret < 0)
1159     {
1160     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1161 sysadm 1.46 p_section->sid, p_article_locate->aid);
1162 sysadm 1.45 return -3;
1163     }
1164     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1165     {
1166     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1167     if (ret < 0)
1168     {
1169     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1170     return -3;
1171     }
1172     }
1173     break;
1174 sysadm 1.64 case SCAN_ARTICLE_BACKWARD_BY_USER:
1175     case SCAN_ARTICLE_FORWARD_BY_USER:
1176     direction = (ret == SCAN_ARTICLE_FORWARD_BY_USER ? 1 : -1);
1177     strncpy(username, p_articles[selected_index]->username, sizeof(username) - 1);
1178     username[sizeof(username) - 1] = '\0';
1179     uid = 0;
1180    
1181     moveto(SCREEN_ROWS, 1);
1182     clrtoeol();
1183     get_data(SCREEN_ROWS, 1,
1184     (direction == 1 ? "向下搜寻作者: " : "向上搜寻作者: "),
1185     username, sizeof(username), BBS_username_max_len);
1186    
1187     if (username[0] == '\0')
1188     {
1189     break;
1190     }
1191    
1192     // Verify format
1193     for (i = 0, ok = 1; ok && username[i] != '\0'; i++)
1194     {
1195     if (!(isalpha(username[i]) || (i > 0 && (isdigit(username[i]) || username[i] == '_'))))
1196     {
1197     ok = 0;
1198     }
1199     }
1200     if (ok && i > BBS_username_max_len)
1201     {
1202     ok = 0;
1203     }
1204     if (!ok)
1205     {
1206     break;
1207     }
1208    
1209     ret = query_user_info_by_username(username, 1, &uid, username_list);
1210     if (ret < 0)
1211     {
1212     log_error("query_user_info_by_username(%s) error\n", username);
1213     break;
1214     }
1215    
1216     if (uid > 0)
1217     {
1218     ret = scan_article_in_section_by_uid(p_section, p_articles[selected_index],
1219     direction, uid, &p_article_locate);
1220     if (ret < 0)
1221     {
1222     log_error("scan_article_in_section_by_uid(sid=%d, aid=%d, direction=%d, uid=%d) error\n",
1223     p_section->sid, p_articles[selected_index]->aid, direction, uid);
1224     return -3;
1225     }
1226     else if (ret == 0) // not found
1227     {
1228     break;
1229     }
1230     }
1231     else // uid == 0
1232     {
1233     ret = scan_article_in_section_by_username(p_section, p_articles[selected_index],
1234     direction, username, &p_article_locate);
1235     if (ret < 0)
1236     {
1237     log_error("scan_article_in_section_by_username(sid=%d, aid=%d, direction=%d, username=%s) error\n",
1238     p_section->sid, p_articles[selected_index]->aid, direction, username);
1239     return -3;
1240     }
1241     else if (ret == 0) // not found
1242     {
1243     break;
1244     }
1245     }
1246    
1247     page_id_cur = page_id;
1248     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1249     &page_id, &selected_index, &article_count);
1250     if (ret < 0)
1251     {
1252     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1253     p_section->sid, p_article_locate->aid);
1254     return -3;
1255     }
1256     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1257     {
1258     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1259     if (ret < 0)
1260     {
1261     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1262     return -3;
1263     }
1264     }
1265     break;
1266 sysadm 1.66 case SCAN_ARTICLE_BACKWARD_BY_TITLE:
1267     case SCAN_ARTICLE_FORWARD_BY_TITLE:
1268     direction = (ret == SCAN_ARTICLE_FORWARD_BY_TITLE ? 1 : -1);
1269    
1270     moveto(SCREEN_ROWS, 1);
1271     clrtoeol();
1272     get_data(SCREEN_ROWS, 1,
1273     (direction == 1 ? "向下搜寻标题: " : "向上搜寻标题: "),
1274     title, sizeof(title), TITLE_SEARCH_MAX_LEN);
1275    
1276     if (title[0] == '\0')
1277     {
1278     break;
1279     }
1280    
1281     ret = scan_article_in_section_by_title(p_section, p_articles[selected_index],
1282     direction, title, &p_article_locate);
1283     if (ret < 0)
1284     {
1285     log_error("scan_article_in_section_by_title(sid=%d, aid=%d, direction=%d, title=%s) error\n",
1286     p_section->sid, p_articles[selected_index]->aid, direction, title);
1287     return -3;
1288     }
1289     else if (ret == 0) // not found
1290     {
1291     break;
1292     }
1293    
1294     page_id_cur = page_id;
1295     ret = locate_article_in_section(p_section, p_article_locate, 0, 0,
1296     &page_id, &selected_index, &article_count);
1297     if (ret < 0)
1298     {
1299     log_error("locate_article_in_section(sid=%d, aid=%d, direction=0, step=0) error\n",
1300     p_section->sid, p_article_locate->aid);
1301     return -3;
1302     }
1303     else if (ret > 0 && page_id != page_id_cur) // found and page changed
1304     {
1305     ret = query_section_articles(p_section, page_id, p_articles, &article_count, &page_count, &ontop_start_offset);
1306     if (ret < 0)
1307     {
1308     log_error("query_section_articles(sid=%d, page_id=%d) error\n", p_section->sid, page_id);
1309     return -3;
1310     }
1311     }
1312     break;
1313 sysadm 1.63 case SEARCH_USER:
1314     user_list_search();
1315     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1316     {
1317     log_error("section_list_draw_screen() error\n");
1318     return -2;
1319     }
1320     break;
1321 sysadm 1.28 case SHOW_HELP:
1322     // Display help information
1323     display_file(DATA_READ_HELP, 1);
1324     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1325     {
1326     log_error("section_list_draw_screen() error\n");
1327     return -2;
1328     }
1329     break;
1330 sysadm 1.37 case VIEW_EX_DIR:
1331     if (section_list_ex_dir_display(p_section) < 0)
1332     {
1333     log_error("section_list_ex_dir_display(sid=%d) error\n", p_section->sid);
1334     }
1335     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1336     {
1337     log_error("section_list_draw_screen() error\n");
1338     return -2;
1339     }
1340     break;
1341 sysadm 1.48 case SHOW_TOP10:
1342     show_top10_menu(NULL);
1343     if (section_list_draw_screen(sname, stitle, master_list, display_nickname) < 0)
1344     {
1345     log_error("section_list_draw_screen() error\n");
1346     return -2;
1347     }
1348     break;
1349 sysadm 1.1 default:
1350     log_error("Unknown command %d\n", ret);
1351     }
1352     }
1353    
1354     return 0;
1355     }
1356 sysadm 1.37
1357     int section_list_ex_dir_display(SECTION_LIST *p_section)
1358     {
1359     MENU_SET ex_menu_set;
1360     int ch = 0;
1361    
1362     if (p_section == NULL)
1363     {
1364     log_error("NULL pointer error\n");
1365     return -1;
1366     }
1367    
1368 sysadm 1.39 if (p_section->ex_menu_tm == 0) // N/A
1369     {
1370     moveto(2, 1);
1371     clrtoeol();
1372 sysadm 1.40 prints("该版块精华区未开放");
1373 sysadm 1.39 press_any_key();
1374     return 0;
1375     }
1376    
1377 sysadm 1.37 if (get_section_ex_menu_set(p_section, &ex_menu_set) < 0)
1378     {
1379     log_error("get_section_ex_menu_set(sid=%d) error\n", p_section->sid);
1380     return -3;
1381     }
1382     if (get_menu_shm_readonly(&ex_menu_set) < 0)
1383     {
1384 sysadm 1.39 log_error("get_menu_shm_readonly(sid=%d) error\n", p_section->sid);
1385 sysadm 1.37 return -3;
1386     }
1387    
1388     clearscr();
1389 sysadm 1.38 show_bottom("");
1390 sysadm 1.37
1391     if (display_menu(&ex_menu_set) == 0)
1392     {
1393     while (!SYS_server_exit)
1394     {
1395     iflush();
1396     ch = igetch(100);
1397 sysadm 1.54
1398     if (ch != KEY_NULL && ch != KEY_TIMEOUT)
1399     {
1400     BBS_last_access_tm = time(NULL);
1401     }
1402    
1403 sysadm 1.37 switch (ch)
1404     {
1405     case KEY_NULL: // broken pipe
1406 sysadm 1.54 log_error("KEY_NULL\n");
1407 sysadm 1.37 return 0;
1408     case KEY_TIMEOUT:
1409     if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME)
1410     {
1411 sysadm 1.54 log_error("User input timeout\n");
1412 sysadm 1.37 return 0;
1413     }
1414     continue;
1415     case CR:
1416     default:
1417     switch (menu_control(&ex_menu_set, ch))
1418     {
1419     case EXITMENU:
1420     ch = EXITMENU;
1421     break;
1422     case REDRAW:
1423     clearscr();
1424 sysadm 1.38 show_bottom("");
1425 sysadm 1.37 display_menu(&ex_menu_set);
1426     break;
1427     case NOREDRAW:
1428     case UNKNOWN_CMD:
1429     default:
1430     break;
1431     }
1432     }
1433    
1434     if (ch == EXITMENU)
1435     {
1436     break;
1437     }
1438     }
1439     }
1440    
1441     detach_menu_shm(&ex_menu_set);
1442    
1443     return 0;
1444     }
1445 sysadm 1.59
1446     int section_aid_locations_save(int uid)
1447     {
1448     char filename[FILE_PATH_LEN];
1449     FILE *fp;
1450     int i;
1451     int ret = 0;
1452    
1453     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1454    
1455     if ((fp = fopen(filename, "wb")) == NULL)
1456     {
1457     log_error("fopen(%s, wb) error: %d\n", filename, errno);
1458     return -1;
1459     }
1460    
1461     for (i = 0; i < p_section_list_pool->section_count; i++)
1462     {
1463     if (fwrite(&(p_section_list_pool->sections[i].sid), sizeof(p_section_list_pool->sections[i].sid), 1, fp) != 1)
1464     {
1465     log_error("fwrite(%s, sid) error\n", filename);
1466     ret = -2;
1467     break;
1468     }
1469    
1470     if (fwrite(&(section_aid_locations[i]), sizeof(section_aid_locations[i]), 1, fp) != 1)
1471     {
1472     log_error("fwrite(%s, aid) error\n", filename);
1473     ret = -2;
1474     break;
1475     }
1476     }
1477    
1478     if (fclose(fp) < 0)
1479     {
1480     log_error("fclose(%s) error: %d\n", filename, errno);
1481     ret = -1;
1482     }
1483    
1484     return ret;
1485     }
1486    
1487     int section_aid_locations_load(int uid)
1488     {
1489     char filename[FILE_PATH_LEN];
1490     FILE *fp;
1491     int i;
1492     int32_t sid;
1493     int32_t aid;
1494     SECTION_LIST *p_section;
1495     int ret = 0;
1496    
1497     snprintf(filename, sizeof(filename), "%s/%d", VAR_SECTION_AID_LOC_DIR, uid);
1498    
1499     if ((fp = fopen(filename, "rb")) == NULL)
1500     {
1501     if (errno == ENOENT) // file not exist
1502     {
1503     return 0;
1504     }
1505     log_error("fopen(%s, rb) error: %d\n", filename, errno);
1506     return -1;
1507     }
1508    
1509     while (!feof(fp))
1510     {
1511     if (fread(&sid, sizeof(sid), 1, fp) != 1)
1512     {
1513     if (ferror(fp) == 0)
1514     {
1515     break;
1516     }
1517     log_error("fread(%s, sid) error: %d\n", filename, ferror(fp));
1518     ret = -2;
1519     break;
1520     }
1521    
1522     if (fread(&aid, sizeof(aid), 1, fp) != 1)
1523     {
1524     if (ferror(fp) == 0)
1525     {
1526     break;
1527     }
1528     log_error("fread(%s, aid) error: %d\n", filename, ferror(fp));
1529     ret = -2;
1530     break;
1531     }
1532    
1533     p_section = section_list_find_by_sid(sid);
1534     if (p_section == NULL)
1535     {
1536     continue; // skip section no longer exist
1537     }
1538    
1539     i = get_section_index(p_section);
1540     if (i < 0)
1541     {
1542     log_error("get_section_index(sid=%d) error\n", sid);
1543     ret = -3;
1544     break;
1545     }
1546     section_aid_locations[i] = aid;
1547     }
1548    
1549     if (fclose(fp) < 0)
1550     {
1551     log_error("fclose(%s) error: %d\n", filename, errno);
1552     ret = -1;
1553     }
1554    
1555     return ret;
1556     }

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