Serenity Operating System
at master 152 lines 4.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibCore/ArgsParser.h> 8#include <LibCore/DateTime.h> 9#include <LibCore/System.h> 10#include <LibMain/Main.h> 11#include <stdio.h> 12#include <string.h> 13#include <time.h> 14 15int const line_width = 70; 16int const line_count = 8; 17int const column_width = 22; 18 19char print_buffer[line_width * line_count]; 20char temp_buffer[line_width * 8]; 21 22int target_day; 23 24int current_year; 25int current_month; 26 27static void append_to_print(char* buffer, int row, int column, char* text) 28{ 29 int starting_point = (line_width * row) + (column * column_width); 30 for (int i = 0; text[i] != '\0'; i++) { 31 buffer[starting_point + i] = text[i]; 32 } 33} 34 35static void insert_month_to_print(int column, int month, int year) 36{ 37 int printing_column = column; 38 int printing_row = 0; 39 40 // FIXME: Both the month name and month header text should be provided by a locale 41 sprintf(temp_buffer, " %02u - %04u ", month, year); 42 append_to_print(print_buffer, printing_row, printing_column, temp_buffer); 43 printing_row++; 44 45 sprintf(temp_buffer, "Su Mo Tu We Th Fr Sa"); 46 append_to_print(print_buffer, printing_row, printing_column, temp_buffer); 47 printing_row++; 48 int day_to_print = 1; 49 auto date_time = Core::DateTime::create(year, month, 1); 50 int first_day_of_week_for_month = date_time.weekday(); 51 int days_in_the_month = date_time.days_in_month(); 52 int last_written_chars = 0; 53 for (int i = 1; day_to_print <= days_in_the_month; ++i) { 54 if (i - 1 < first_day_of_week_for_month) { 55 last_written_chars += sprintf(temp_buffer + last_written_chars, " "); 56 } else { 57 if (year == current_year && month == current_month && target_day == day_to_print) { 58 // FIXME: To replicate Unix cal it would be better to use "\x1b[30;47m%2d\x1b[0m " in here instead of *. 59 // However, doing that messes up the layout. 60 last_written_chars += sprintf(temp_buffer + last_written_chars, "%2d*", day_to_print); 61 } else { 62 last_written_chars += sprintf(temp_buffer + last_written_chars, "%2d ", day_to_print); 63 } 64 day_to_print++; 65 } 66 67 append_to_print(print_buffer, printing_row, printing_column, temp_buffer); 68 69 if (i % 7 == 0) { 70 printing_row++; 71 memset(temp_buffer, ' ', line_width * 8); 72 temp_buffer[line_width * 8 - 1] = '\0'; 73 last_written_chars = 0; 74 } 75 } 76} 77 78static void clean_buffers() 79{ 80 for (int i = 1; i < line_width * line_count; ++i) { 81 print_buffer[i - 1] = i % line_width == 0 ? '\n' : ' '; 82 } 83 print_buffer[line_width * line_count - 1] = '\0'; 84 85 for (int i = 0; i < line_width; ++i) { 86 temp_buffer[i] = ' '; 87 } 88 temp_buffer[line_width - 1] = '\0'; 89} 90 91ErrorOr<int> serenity_main(Main::Arguments arguments) 92{ 93 TRY(Core::System::pledge("stdio rpath")); 94 TRY(Core::System::unveil("/etc/timezone", "r")); 95 TRY(Core::System::unveil(nullptr, nullptr)); 96 97 int day = 0; 98 int month = 0; 99 int year = 0; 100 101 Core::ArgsParser args_parser; 102 args_parser.set_general_help("Display a nice overview of a month or year, defaulting to the current month."); 103 // FIXME: This should ensure two values get parsed as month + year 104 args_parser.add_positional_argument(day, "Day of year", "day", Core::ArgsParser::Required::No); 105 args_parser.add_positional_argument(month, "Month", "month", Core::ArgsParser::Required::No); 106 args_parser.add_positional_argument(year, "Year", "year", Core::ArgsParser::Required::No); 107 args_parser.parse(arguments); 108 109 time_t now = time(nullptr); 110 auto* tm = localtime(&now); 111 112 // Hack: workaround two values parsing as day + month. 113 if (day && month && !year) { 114 year = month; 115 month = day; 116 day = 0; 117 } 118 119 bool year_mode = !day && !month && year; 120 121 if (!year) 122 year = tm->tm_year + 1900; 123 if (!month) 124 month = tm->tm_mon + 1; 125 if (!day) 126 day = tm->tm_mday; 127 128 current_year = year; 129 current_month = month; 130 131 clean_buffers(); 132 133 if (year_mode) { 134 out(" Year {:04} ", year); 135 outln(); 136 outln(); 137 138 for (int i = 1; i < 12; ++i) { 139 insert_month_to_print(0, i++, year); 140 insert_month_to_print(1, i++, year); 141 insert_month_to_print(2, i, year); 142 outln("{}", print_buffer); 143 clean_buffers(); 144 } 145 } else { 146 insert_month_to_print(0, month, year); 147 outln("{}", print_buffer); 148 clean_buffers(); 149 } 150 151 return 0; 152}