/[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.46 - (hide annotations)
Mon Oct 13 02:23:27 2025 UTC (5 months ago) by sysadm
Branch: MAIN
Changes since 1.45: +52 -6 lines
Content type: text/x-csrc
Support locate at specific article while listing section articles
Remember last located article of each section, before logout

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

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