00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "stdafx.h"
00013 #include "fileio_func.h"
00014 #include "fontcache.h"
00015 #include "gfx_type.h"
00016 #include "gfx_func.h"
00017 #include "string_func.h"
00018 #include "textfile_gui.h"
00019
00020 #include "widgets/misc_widget.h"
00021
00022 #include "table/strings.h"
00023
00024
00026 static const NWidgetPart _nested_textfile_widgets[] = {
00027 NWidget(NWID_HORIZONTAL),
00028 NWidget(WWT_CLOSEBOX, COLOUR_MAUVE),
00029 NWidget(WWT_CAPTION, COLOUR_MAUVE, WID_TF_CAPTION), SetDataTip(STR_NULL, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
00030 NWidget(WWT_DEFSIZEBOX, COLOUR_MAUVE),
00031 EndContainer(),
00032 NWidget(NWID_HORIZONTAL),
00033 NWidget(WWT_PANEL, COLOUR_MAUVE, WID_TF_BACKGROUND), SetMinimalSize(200, 125), SetResize(1, 12), SetScrollbar(WID_TF_VSCROLLBAR),
00034 EndContainer(),
00035 NWidget(NWID_VERTICAL),
00036 NWidget(NWID_VSCROLLBAR, COLOUR_MAUVE, WID_TF_VSCROLLBAR),
00037 EndContainer(),
00038 EndContainer(),
00039 NWidget(NWID_HORIZONTAL),
00040 NWidget(NWID_HSCROLLBAR, COLOUR_MAUVE, WID_TF_HSCROLLBAR),
00041 NWidget(WWT_RESIZEBOX, COLOUR_MAUVE),
00042 EndContainer(),
00043 };
00044
00046 static WindowDesc _textfile_desc(
00047 WDP_CENTER, "textfile", 630, 460,
00048 WC_TEXTFILE, WC_NONE,
00049 0,
00050 _nested_textfile_widgets, lengthof(_nested_textfile_widgets)
00051 );
00052
00053 TextfileWindow::TextfileWindow(TextfileType file_type) : Window(&_textfile_desc), file_type(file_type)
00054 {
00055 this->CreateNestedTree();
00056 this->vscroll = this->GetScrollbar(WID_TF_VSCROLLBAR);
00057 this->hscroll = this->GetScrollbar(WID_TF_HSCROLLBAR);
00058 this->FinishInitNested();
00059 this->GetWidget<NWidgetCore>(WID_TF_CAPTION)->SetDataTip(STR_TEXTFILE_README_CAPTION + file_type, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS);
00060 }
00061
00062 TextfileWindow::~TextfileWindow()
00063 {
00064 free(this->text);
00065 }
00066
00067 void TextfileWindow::UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
00068 {
00069 switch (widget) {
00070 case WID_TF_BACKGROUND:
00071 this->line_height = FONT_HEIGHT_MONO + 2;
00072 resize->height = this->line_height;
00073
00074 size->height = 4 * resize->height + TOP_SPACING + BOTTOM_SPACING;
00075 size->width = max(200u, size->width);
00076 break;
00077 }
00078 }
00079
00080 void TextfileWindow::DrawWidget(const Rect &r, int widget) const
00081 {
00082 if (widget != WID_TF_BACKGROUND) return;
00083
00084 int width = r.right - r.left + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT;
00085 int height = r.bottom - r.top + 1 - WD_BEVEL_LEFT - WD_BEVEL_RIGHT;
00086
00087 DrawPixelInfo new_dpi;
00088 if (!FillDrawPixelInfo(&new_dpi, r.left + WD_BEVEL_LEFT, r.top, width, height)) return;
00089 DrawPixelInfo *old_dpi = _cur_dpi;
00090 _cur_dpi = &new_dpi;
00091
00092 int left, right;
00093 if (_current_text_dir == TD_RTL) {
00094 left = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - this->hscroll->GetCount();
00095 right = width + WD_BEVEL_RIGHT - WD_FRAMETEXT_RIGHT - 1 + this->hscroll->GetPosition();
00096 } else {
00097 left = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT - this->hscroll->GetPosition();
00098 right = WD_FRAMETEXT_LEFT - WD_BEVEL_LEFT + this->hscroll->GetCount() - 1;
00099 }
00100 int top = TOP_SPACING;
00101 for (uint i = 0; i < this->vscroll->GetCapacity() && i + this->vscroll->GetPosition() < this->lines.Length(); i++) {
00102 DrawString(left, right, top + i * this->line_height, this->lines[i + this->vscroll->GetPosition()], TC_WHITE, SA_LEFT, false, FS_MONO);
00103 }
00104
00105 _cur_dpi = old_dpi;
00106 }
00107
00108 void TextfileWindow::OnResize()
00109 {
00110 this->vscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND, TOP_SPACING + BOTTOM_SPACING);
00111 this->hscroll->SetCapacityFromWidget(this, WID_TF_BACKGROUND);
00112 }
00113
00114 void TextfileWindow::Reset()
00115 {
00116 this->search_iterator = 0;
00117 }
00118
00119 FontSize TextfileWindow::DefaultSize()
00120 {
00121 return FS_MONO;
00122 }
00123
00124 const char *TextfileWindow::NextString()
00125 {
00126 if (this->search_iterator >= this->lines.Length()) return NULL;
00127
00128 return this->lines[this->search_iterator++];
00129 }
00130
00131 bool TextfileWindow::Monospace()
00132 {
00133 return true;
00134 }
00135
00136 void TextfileWindow::SetFontNames(FreeTypeSettings *settings, const char *font_name)
00137 {
00138 #ifdef WITH_FREETYPE
00139 strecpy(settings->mono_font, font_name, lastof(settings->mono_font));
00140 #endif
00141 }
00142
00146 void TextfileWindow::LoadTextfile(const char *textfile, Subdirectory dir)
00147 {
00148 if (textfile == NULL) return;
00149
00150 this->lines.Clear();
00151
00152
00153 size_t filesize;
00154 FILE *handle = FioFOpenFile(textfile, "rb", dir, &filesize);
00155 if (handle == NULL) return;
00156
00157 this->text = ReallocT(this->text, filesize + 1);
00158 size_t read = fread(this->text, 1, filesize, handle);
00159 fclose(handle);
00160
00161 if (read != filesize) return;
00162
00163 this->text[filesize] = '\0';
00164
00165
00166 for (char *p = this->text; *p != '\0'; p++) {
00167 if (*p == '\t' || *p == '\r') *p = ' ';
00168 }
00169
00170
00171 char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0);
00172
00173
00174 str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
00175
00176
00177 *this->lines.Append() = p;
00178 for (; *p != '\0'; p++) {
00179 if (*p == '\n') {
00180 *p = '\0';
00181 *this->lines.Append() = p + 1;
00182 }
00183 }
00184
00185 CheckForMissingGlyphs(true, this);
00186
00187
00188 this->vscroll->SetCount(this->lines.Length());
00189
00190 this->max_length = 0;
00191 for (uint i = 0; i < this->lines.Length(); i++) {
00192 this->max_length = max(this->max_length, GetStringBoundingBox(this->lines[i], FS_MONO).width);
00193 }
00194 this->hscroll->SetCount(this->max_length + WD_FRAMETEXT_LEFT + WD_FRAMETEXT_RIGHT);
00195 this->hscroll->SetStepSize(10);
00196 }
00197
00205 const char *GetTextfile(TextfileType type, Subdirectory dir, const char *filename)
00206 {
00207 static const char * const prefixes[] = {
00208 "readme",
00209 "changelog",
00210 "license",
00211 };
00212 assert_compile(lengthof(prefixes) == TFT_END);
00213
00214 const char *prefix = prefixes[type];
00215
00216 if (filename == NULL) return NULL;
00217
00218 static char file_path[MAX_PATH];
00219 strecpy(file_path, filename, lastof(file_path));
00220
00221 char *slash = strrchr(file_path, PATHSEPCHAR);
00222 if (slash == NULL) return NULL;
00223
00224 seprintf(slash + 1, lastof(file_path), "%s_%s.txt", prefix, GetCurrentLanguageIsoCode());
00225 if (FioCheckFileExists(file_path, dir)) return file_path;
00226
00227 seprintf(slash + 1, lastof(file_path), "%s_%.2s.txt", prefix, GetCurrentLanguageIsoCode());
00228 if (FioCheckFileExists(file_path, dir)) return file_path;
00229
00230 seprintf(slash + 1, lastof(file_path), "%s.txt", prefix);
00231 return FioCheckFileExists(file_path, dir) ? file_path : NULL;
00232 }