/***************************************************************************** * DikuMUD (C) 1990, 1991 by: * * Sebastian Hammer, Michael Seifert, Hans Henrik Staefeldt, Tom Madsen, * * and Katja Nyboe. * *---------------------------------------------------------------------------* * MERC 2.1 (C) 1992, 1993 by: * * Michael Chastain, Michael Quan, and Mitchell Tse. * *---------------------------------------------------------------------------* * SMAUG 1.4 (C) 1994, 1995, 1996, 1998 by: Derek Snider. * * Team: Thoric, Altrag, Blodkai, Narn, Haus, Scryn, Rennard, Swordbearer, * * gorog, Grishnakh, Nivek, Tricops, and Fireblade. * *---------------------------------------------------------------------------* * SMAUG 1.7 FUSS by: Samson and others of the SMAUG community. * * Their contributions are greatly appreciated. * *---------------------------------------------------------------------------* * LoP (C) 2006, 2007, 2008 by: the LoP team. * *****************************************************************************/ #include <string.h> #include <stdio.h> #include <time.h> #include "h/mud.h" #include "h/news.h" NEWS_DATA *first_news, *last_news; int top_news; void free_news( NEWS_DATA *news ) { STRFREE( news->text ); STRFREE( news->poster ); STRFREE( news->modified_by ); DISPOSE( news ); } void remove_news( NEWS_DATA *news ) { UNLINK( news, first_news, last_news, next, prev ); top_news--; } void free_all_news( void ) { NEWS_DATA *news, *news_next; for( news = first_news; news; news = news_next ) { news_next = news->next; remove_news( news ); free_news( news ); } } void add_news( NEWS_DATA *news ) { LINK( news, first_news, last_news, next, prev ); top_news++; } /* Check to see if argument matches date of news in some way */ bool check_date( NEWS_DATA *news, char *argument ) { char buf[MIL]; struct tm *time; int check = 0, day = 0, month = 0, year = 0; if( !news ) return false; time = localtime( &news->added ); day = time->tm_mday; month = ( time->tm_mon + 1 ); year = ( time->tm_year + 1900 ); /* Full date */ snprintf( buf, sizeof( buf ), "%d/%d/%d", month, day, year ); if( !str_cmp( buf, argument ) ) return true; /* Month and day */ snprintf( buf, sizeof( buf ), "%d/%d", month, day ); if( !str_cmp( buf, argument ) ) return true; /* Month and year */ snprintf( buf, sizeof( buf ), "%d/%d", month, year ); if( !str_cmp( buf, argument ) ) return true; /* Day and Year */ snprintf( buf, sizeof( buf ), "%d/%d", day, year ); if( !str_cmp( buf, argument ) ) return true; /* Month, day, or year */ check = atoi( argument ); if( check == month || check == day || check == year ) return true; return false; } void save_news( void ) { NEWS_DATA *news; FILE *fp; if( !first_news ) { remove_file( NEWS_FILE ); return; } if( !( fp = fopen( NEWS_FILE, "w" ) ) ) return; for( news = first_news; news; news = news->next ) { fprintf( fp, "%s", "#NEWS\n" ); if( news->poster ) fprintf( fp, "Poster %s~\n", news->poster ); fprintf( fp, "Level %d\n", news->level ); fprintf( fp, "Time %ld\n", news->added ); if( news->modified ) fprintf( fp, "Modified %ld\n", news->modified ); if( news->modified_by ) fprintf( fp, "ModifiedBy %s~\n", news->modified_by ); if( news->text ) fprintf( fp, "Text %s~\n", strip_cr( news->text ) ); fprintf( fp, "%s", "End\n\n" ); } fprintf( fp, "%s", "#END\n" ); fclose( fp ); fp = NULL; } void fread_news( FILE *fp ) { const char *word; bool fMatch; NEWS_DATA *news; CREATE( news, NEWS_DATA, 1 ); for( ;; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = false; switch( UPPER( word[0] ) ) { case '*': fMatch = true; fread_to_eol( fp ); break; case 'E': if( !str_cmp( word, "End" ) ) { add_news( news ); return; } break; case 'L': KEY( "Level", news->level, fread_number( fp ) ); break; case 'M': KEY( "Modified", news->modified, fread_time( fp ) ); KEY( "ModifiedBy", news->modified_by, fread_string( fp ) ); break; case 'P': KEY( "Poster", news->poster, fread_string( fp ) ); break; case 'T': KEY( "Text", news->text, fread_string( fp ) ); KEY( "Time", news->added, fread_time( fp ) ); break; } if( !fMatch ) { bug( "%s: no match: %s", __FUNCTION__, word ); fread_to_eol( fp ); } } free_news( news ); } void load_news( void ) { FILE *fp; top_news = 0; first_news = last_news = NULL; if( !( fp = fopen( NEWS_FILE, "r" ) ) ) return; for( ;; ) { char letter; char *word; letter = fread_letter( fp ); if( letter == '*' ) { fread_to_eol( fp ); continue; } if( letter != '#' ) { bug( "%s: # not found.", __FUNCTION__ ); break; } word = fread_word( fp ); if( !str_cmp( word, "NEWS" ) ) { fread_news( fp ); continue; } else if( !str_cmp( word, "END" ) ) break; else { bug( "%s: bad section (%s).", __FUNCTION__, word ); fread_to_eol( fp ); continue; } } fclose( fp ); fp = NULL; } /* Find a specif news entry using a number */ NEWS_DATA *find_news( CHAR_DATA *ch, int num ) { NEWS_DATA *news; int cnt = 0; if( !ch ) return NULL; for( news = first_news; news; news = news->next ) { if( get_trust( ch ) < news->level ) continue; if( ++cnt == num ) return news; } return NULL; } void show_news( CHAR_DATA *ch, NEWS_DATA *news, int count ) { ch_printf( ch, "&C[&W%4d&C] &CPosted by &W%s on %s\r\n", count, news->poster, distime( news->added ) ); if( news->modified ) ch_printf( ch, "&CLast modified by &W%s on %s\r\n", news->modified_by ? news->modified_by : "(Unknown)", distime( news->modified ) ); ch_printf( ch, "&W%s&D\r\n", news->text ? news->text : "(Nothing set for the text)" ); } CMDF( do_news ) { NEWS_DATA *news; int count = 0, displayed = 0; char arg[MIL]; bool udate = false; if( is_npc( ch ) ) { send_to_char( "NPCs have no reason to do news.\r\n", ch ); return; } if( !ch->desc ) { send_to_char( "You have no descriptor.\r\n", ch ); return; } switch( ch->substate ) { default: break; case SUB_HELP_EDIT: if( !( news = ( NEWS_DATA * ) ch->dest_buf ) ) { bug( "%s: sub_help_edit: NULL ch->dest_buf", __FUNCTION__ ); stop_editing( ch ); return; } STRFREE( news->text ); news->text = copy_buffer( ch ); stop_editing( ch ); save_news( ); return; } set_pager_color( AT_HELP, ch ); argument = one_argument( argument, arg ); /* should we use date? */ if( !str_cmp( arg, "date" ) ) { udate = true; argument = one_argument( argument, arg ); } /* Add a new news entry */ if( arg && arg[0] != '\0' && !str_cmp( arg, "add" ) ) { CREATE( news, NEWS_DATA, 1 ); if( !argument || argument[0] == '\0' || !is_number( argument ) ) news->level = 0; else news->level = URANGE( 0, atoi( argument ), MAX_LEVEL ); ch->substate = SUB_HELP_EDIT; ch->dest_buf = news; news->poster = STRALLOC( ch->name ); news->added = current_time; add_news( news ); start_editing( ch, news->text ); return; } /* Show all the news data if no arg or not a number or using a date */ if( !arg || arg[0] == '\0' || !is_number( arg ) || udate ) { for( news = first_news; news; news = news->next ) { if( get_trust( ch ) < news->level ) continue; count++; if( arg && arg[0] != '\0' && str_cmp( arg, news->poster ) && !check_date( news, arg ) ) continue; else if( ( !arg || arg[0] == '\0' ) && ch->pcdata && news != last_news && news->added <= ch->pcdata->news_read ) continue; displayed++; show_news( ch, news, count ); if( ch->pcdata && news->added > ch->pcdata->news_read ) ch->pcdata->news_read = news->added; /* Limit the max it shows to 20? */ if( displayed == 20 ) break; } if( displayed == 0 ) { if( !arg || arg[0] == '\0' ) send_to_char( "No news to show.\r\n", ch ); else ch_printf( ch, "No news found matching %s.\r\n", arg ); } return; } count = atoi( arg ); if( !( news = find_news( ch, count ) ) ) { send_to_char( "No such news to modify.\r\n", ch ); return; } argument = one_argument( argument, arg ); if( !arg || arg[0] == '\0' || !is_immortal( ch ) ) { show_news( ch, news, count ); return; } /* Remove a news entry */ if( !str_cmp( arg, "remove" ) ) { remove_news( news ); save_news( ); send_to_char( "That news was removed and the news was saved.\r\n", ch ); return; } /* Edit a news entry, only changes the text */ if( !str_cmp( arg, "edit" ) ) { ch->substate = SUB_HELP_EDIT; ch->dest_buf = news; STRSET( news->modified_by, ch->name ); news->modified = current_time; start_editing( ch, news->text ); return; } if( !str_cmp( arg, "level" ) ) { if( !argument || argument[0] == '\0' || !is_number( argument ) ) news->level = 0; else news->level = URANGE( 0, atoi( argument ), MAX_LEVEL ); save_news( ); ch_printf( ch, "Level on that news is now %d and the news has been saved.\r\n", news->level ); return; } /* Handle displaying it again if the right argument wasnt given */ show_news( ch, news, count ); }