0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

71歳の... PC98時代の定番ファイラー「FD」やエディター「sedit」のようなモノが作りたくて

Last updated at Posted at 2025-10-15

07Editor2.jpg

以前、ESP32-S3でDOSコマンドベース風の「ナンチャッテPC」
https://qiita.com/Mobu_Kyoto/items/fa8da97f9ffc481243d1
を作りました。今回は、懐かしい「FD」「sedit」風のファイラー、エディターもどきを作成してみました。もちろん、本家の足元にも及びませんが、500行内に収めることを大前提に、ヘルプ表示機能も付けられ何とか満足なモノが出来ました。既に投稿済みの
https://qiita.com/Mobu_Kyoto/items/bf53d6ece12c533fd5fe
をアップデートしようとも思いましたが、新たな投稿にします。
 環境/構成は以下。

1.Windows 11 Pro 24H2
2.Arduino IDE 2.3.6
3.Freenove ESP32-S3 WROOM (8MB Flash,8MB PSRAM) ボード「FNK0085」
    付属カメラなしで使用
    Arduino IDE上では「ESP32S3 Dev Module」
4.SD関係でエラーが出ることがありますが、ボード内蔵microSDスロットで
    "SD_MMC.h"使用であれば問題なし(?)
    スケッチと同じフォルダーに"sd_read_write.cpp"、"sd_read_write.h"をコピー
    ボードマネージャは最新の"esp32 by Espressif Systems 3.3.2"
5.7"インチ800x480 TFTモジュール、16bitパラレル接続
    「LovyanGFX」ライブラリーを使用
    電力補充のため外部5V電源接続
6.次のツールオプションを設定してコンパイル
    Flash Size: "8MB(64Mb)"
    Partition Schem:"Huge APP ...
    PSRAM: "OPI PSRAM"
7.キー入力は「Tera Term」を通して行う
    キー推しっ放しにも対応してくれる

 LovyanGFXで必要なヘッダファイルは次。これをスケッチと同じフォルダーにコピーしておきます。

myLovyanGFX.hpp
#pragma once
#define LGFX_USE_V1
#include <LovyanGFX.hpp>

class LGFX : public lgfx::LGFX_Device {
  lgfx::Panel_SSD1963 _panel_instance;
  lgfx::Bus_Parallel16 _bus_instance;  //16bit Parallelのインスタンス(ESP32s3)
public:
  LGFX(void) {  // バス制御の設定を行います。
    auto cfg = _bus_instance.config();  // バス設定用の構造体を取得します。
    // 16ビットパラレルバスの設定
    cfg.freq_write = 20000000;  // 送信クロック(最大20MHz,80MHzを整数割の値に丸める)
    cfg.pin_wr = 46;             // WR を接続しているピン番号
    cfg.pin_rd =  3;            //14;                        // RD を接続しているピン番号
    cfg.pin_rs =  9;            //3;                        // RS(D/C)を接続しているピン番号

    cfg.pin_d0 = 21;            // D0 を接続しているピン番号
    cfg.pin_d1 = 47;            // 0;//36;                        // D1 を接続しているピン番号
    cfg.pin_d2 = 45;            // D2 を接続しているピン番号
    cfg.pin_d3 =  0;             //35;//38;//37;                        // D3 を接続しているピン番号
    cfg.pin_d4 = 41;            // D4 を接続しているピン番号
    cfg.pin_d5 = 42;            //36;//39;//38;                        // D5 を接続しているピン番号
    cfg.pin_d6 =  2;             // D6 を接続しているピン番号s
    cfg.pin_d7 =  1;             //37;//40;//39;                        // D7 を接続しているピン番号

    cfg.pin_d8 =  8;//14;            //2;                        // D8 を接続しているピン番号
    cfg.pin_d9 = 18;//13;            // D9 を接続しているピン番号
    cfg.pin_d10= 17;//12;           //42;                        // D10を接続しているピン番号
    cfg.pin_d11= 16;//11;           // D11を接続しているピン番号
    cfg.pin_d12= 15;//10;            //41;                        // D12を接続しているピン番号
    cfg.pin_d13=  7;//9;            // D13を接続しているピン番号
    cfg.pin_d14=  6;//46;            //40;                        // D14を接続しているピン番号
    cfg.pin_d15=  5;//3;            // D15を接続しているピン番号
    _bus_instance.config(cfg);  // 設定値をバスに反映します。
    _panel_instance.setBus(&_bus_instance);  // バスをパネルにセットします。

    {  // 表示パネル制御の設定
      auto cfg = _panel_instance.config();  // 表示パネル設定用の構造体を取得します。
      cfg.pin_cs = 4;                       //8;           // CSが接続されているピン番号   (-1 = disable)
      cfg.pin_rst = -1;                     //9;      // RSTが接続されているピン番号  (-1 = disable)
      cfg.pin_busy = -1;                    // BUSYが接続されているピン番号 (-1 = disable)
      cfg.memory_width = 800;               // ドライバICがサポートしている最大の幅
      cfg.memory_height = 480;              // ドライバICがサポートしている最大の高さ
      cfg.panel_width = 800;                // 実際に表示可能な幅
      cfg.panel_height = 480;               // 実際に表示可能な高さ
      cfg.offset_x = 0;                     // パネルのX方向オフセット量
      cfg.offset_y = 0;                     // パネルのY方向オフセット量
      cfg.offset_rotation = 0;              // 回転方向の値のオフセット 0~7 (4~7は上下反転)
      cfg.dummy_read_pixel = 8;             // ピクセル読出し前のダミーリードのビット数
      cfg.dummy_read_bits = 1;              // ピクセル以外のデータ読出し前のダミーリードのビット数
      cfg.readable = true;                  // データ読出しが可能な場合 trueに設定
      cfg.invert = false;                   // パネルの明暗が反転してしまう場合 trueに設定
      cfg.rgb_order = true;                 // パネルの赤と青が入れ替わってしまう場合 trueに設定
      cfg.dlen_16bit = true;                // データ長を16bit単位で送信するパネルの場合trueに設定
      cfg.bus_shared = false;               // SDカードとバス共有はtrueに設定
      _panel_instance.config(cfg);
    }
    {  // mode and resolution 18bit/24bit 設定
      auto cfg = _panel_instance.config_timing_params();
      // cfg.data_width = lgfx::Panel_SSD1963::is18bit;         // 18bitパネル
      cfg.data_width = lgfx::Panel_SSD1963::is18bit_dithering;  // 18bitパネル(ディザリング有効)
      // cfg.data_width = lgfx::Panel_SSD1963::is18bit_FRC;     // 18bitパネル(FRC有効)
      // cfg.data_width = lgfx::Panel_SSD1963::is24bit;         // 24bitパネル
      cfg.pll_clock = 160000000;                                // pll_clock設定
      cfg.refresh_rate = 100;                                   // リフレッシュレート設定
      _panel_instance.config_timing_params(cfg);
    }

    setPanel(&_panel_instance);  // 使用するパネルをセットします。
  }
};

スケッチ本体です。

07_Fn_Filer_TeTm_2.ino
/*--------------------------
"esp32 by Espressif Systems ver.3.3.2" 
HUGE APP"3MB...
PSRAM:OPI PSRAM

最大3145728バイトのフラッシュメモリのうち、スケッチが939671バイト(29%)を使っています。
最大327680バイトのRAMのうち、グローバル変数が34424バイト(10%)を使っていて、ローカル変数で293256バイト使うことができます。
esptool v5.1.0
Chip type:          ESP32-S3 (QFN56) (revision v0.2)
Features:           Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded PSRAM 8MB (AP_3v3)
Crystal frequency:  40MHz
--------------------------*/
#include "sd_read_write.h"
#include "SD_MMC.h"
#include <myLovyanGFX.hpp>
#include <string>
#include <vector>
using namespace std;

// FREENOVE ESP32-S3 WROOM 内蔵SD_MMC スロット使用のため
#define SD_MMC_CMD 38  // MISO. Please do not modify it.
#define SD_MMC_CLK 39  // CLK.  Please do not modify it.
#define SD_MMC_D0 40   // MOSI. Please do not modify it.
#define SW 800
#define SH 480
#define _LH 22            // line feed height
#define fnLs 20           // display rows at dir files
#define maxDispLines 20   //18
#define maxTextLines 256  // not over
#define maxFiles 128      // Define maximum number of files to store

LGFX lcd;
LGFX_Sprite spr0(&lcd);      // filename Box
LGFX_Sprite spr1(&lcd);      // Edit-text area
String fileNames[maxFiles];  // Array to store file names
uint16_t filesCount = 0;
uint16_t chosenFile = 0;
uint8_t fListPage = 0;
uint8_t H_lebel = 0;
String dirName = "";
String fileName = "*.txt, *.c, *.cpp";
String txt[maxTextLines];
String spc[maxTextLines];
uint16_t cuX[maxTextLines];
bool mode = 0;          // 0 is edit fileName, 1 is edit content lines
bool openMenu = false;  // dir/open files menu
unsigned short modeColor[2] = { TFT_PURPLE, TFT_SILVER };
uint16_t line = 0;      // present edit-line
uint16_t lastline = 0;  // content lines
uint16_t lb = 0;        // scroll base line
std::vector<String> help1 = {
  "- When Dir files/dirs -",
  "ENTER: Select the file",
  "UP   : DIR previous file",
  "DOWN : DIR next file",
  "LEFT : DIR previous page",
  "RIGHT: DIR next page",
  "ESC  : Back"
};
std::vector<String> help2 = {
  "- When Editing file -",
  "ESC  : Back",
  "F5   : Save file",
  "UP   : Previous line",
  "DOWN : Next line",
  "LEFT : Previous char",
  "RIGHT: Next char",
  "ENTER: Ins' a line or separate the line",
  "DELETE   : Delete the char or NL/LF",
  "BACKSPACE: Delete prev char or NL/LF"
};
void DispHelp(uint16_t x, uint16_t y, std::vector<String> s) {
  lcd.drawRect(50, 0, 247, 24, modeColor[1]);
  lcd.setTextColor(TFT_YELLOW);
  for (uint8_t i = 0; i < s.size(); i++)
    lcd.drawString(s[i], x, y + i * 25);
}
void FKey(String s1, String s2, uint16_t x, uint16_t y) {
  lcd.fillRect(x, y, 90, 22, TFT_SILVER);
  lcd.setTextColor(TFT_MAGENTA);
  lcd.drawString(s1, x + 3, y + 2);
  lcd.setTextColor(TFT_BLACK);
  lcd.drawString(s2, x + 30, y + 2);
}
void setup(void) {
  Serial.begin(115200);
  lcd.begin();
  lcd.setRotation(0);
  lcd.fillScreen(TFT_NAVY);
  lcd.fillRect(1, 26, SW - 1, SH - 26, TFT_NAVY);
  lcd.setFont(&fonts::efontJA_16_b);   // Japanese available monospaced font.
  spr0.setFont(&fonts::efontJA_16_b);  // 95 chars in a line on 800 wide pixels screen.
  spr1.setFont(&fonts::efontJA_16_b);
  spr0.setColorDepth(1);
  spr0.createSprite(245, 22);  // filename editbox
  spr1.setColorDepth(3);       // 2^3=8 colors pallet. needs 5 colors.
  spr1.createSprite(SW - 2, _LH);
  spr1.setPaletteColor(2, TFT_LIGHTGRAY);  // focused line background
  spr1.setPaletteColor(3, TFT_MAGENTA);    // cursor color
  spr1.setPaletteColor(4, TFT_GREEN);      // text color is GREEN
  lcd.setTextColor(TFT_YELLOW);
  lcd.drawString("FILE:", 14, 3);
  FKey("F1", " DIR", 305, 1);
  FKey("F2", " NEW", 405, 1);
  FKey("F3", "Fi/Ed", 505, 1);
  FKey("F4", "SAVE", 605, 1);
  FKey("F5", "HELP", 705, 1);
  SD_MMC.setPins(SD_MMC_CLK, SD_MMC_CMD, SD_MMC_D0);
  if (!SD_MMC.begin("/sdcard", true, true, SDMMC_FREQ_DEFAULT, 5)) {
    Serial.println(F("Card Mount Failed."));
    return;
  } else {                                 // Card Monted Successfully.
    uint8_t cardType = SD_MMC.cardType();  // カード情報
    String s = "Card Type: ";
    if (cardType == CARD_MMC) s += "MMC";
    else if (cardType == CARD_SD) s += "SDSC";
    else if (cardType == CARD_SDHC) s += "SDHC";
    else s += "UNKNOWN";
    Serial.println(s);
    Serial.printf("Card Size: %d GB\r\n", SD_MMC.cardSize() >> 30);  // /(1024 * 1024 * 1024));
  }
}
void loop(void) {
  lcd.drawRect(50, 0, 247, 24, modeColor[mode]);
  lcd.drawRect(1, 26, SW - 2, SH - 26, modeColor[!mode]);

  while (Serial.available() == 0) { ; }
  uint8_t intC = Serial.read();
  String intS;
  // FuncKey superiority --------------------------------------------
  if (intC < ' ' || intC > '~') {  // out of Ascii
    intS = (String)intC;
    while (Serial.available()) {  // get string for like Function keys.
      uint8_t k = Serial.read();
      intS = intS + (String)k;
    }
    Serial.printf("%c ; %s\n\r", intC, intS);
    if (intS.equals("277980")) {  // F1 Dir
      H_lebel = 0;
      dirName = "";
      openMenu = true;  // "Dir /"
      clsTextArea(dirName);
      listupFiles("/");  // store to fileNames[]
      dispFiles(fListPage);
    }
    if (intS.equals("277981")) {  // F2 New file
      fileName = "*.txt";
      clsTextArea(fileName);
      openMenu = false;
      mode = 0;
    }
    if (intS.equals("277982")) {  // F3 switch edit fileneme/content
      mode = !mode;               // toggle filename or content
      lcd.drawRect(50, 0, 247, 24, modeColor[mode]);
      lcd.drawRect(1, 26, SW - 2, SH - 26, modeColor[!mode]);
    }
    if (intS.equals("27914953126")) {  //F5 HELP
      lcd.fillRect(1, 26, SW - 1, SH - 26, TFT_NAVY);
      DispHelp(40, 60, help1);
      DispHelp(400, 60, help2);
    }
    //if (intS.equals("27914957126")) Serial.println("F8");
    //if (intS.equals("27915048126")) Serial.println("F9");
    //if (intS.equals("27915049126")) Serial.println("F10");
    //if (intS.equals("27915051126")) Serial.println("F11");
    //if (intS.equals("27915052126")) Serial.println("F12");
  }  // FuncKey superiority end ------------------------------------------

  if (openMenu) {                 // File-Choosing mode
    if (intS.equals("279168")) {  // LEFT previous list page
      if (fListPage > 0) {
        chosenFile = --fListPage * fnLs;
        dispFiles(fListPage);
      }
    }
    if (intS.equals("279167")) {  // RIGHT next list page
      if (filesCount > fnLs * (fListPage + 1)) {
        chosenFile = ++fListPage * fnLs;
        dispFiles(fListPage);
      }
    }
    if (intS.equals("27")) {  // ESC -> dir upper hierarchy
      if (H_lebel > 0) {      // not root directory;
        H_lebel--;
        uint8_t result = dirName.lastIndexOf('/');
        if (result > 0) dirName = dirName.substring(0, result);
      }
      if (H_lebel == 0) dirName = "";  // coased by "H_lebel--""
      Serial.printf("%s; lebel=%d", dirName, H_lebel);
      fileName = dirName;
      listupFiles(dirName);
      dispFiles(fListPage);
    }
    if (intC == 13) {  // RETURN -> choose file/folder
      fileName = fileNames[chosenFile];
      clsTextArea(fileName);
      if (fileName.substring(fileName.length() - 1, fileName.length()) == "/") {  // isdirectory
        dirName += "/" + fileName.substring(0, fileName.length() - 1);
        Serial.printf("%s; lebel=%d", dirName, ++H_lebel);
        listupFiles(dirName);  // list up files in the directory
        chosenFile = 0;
        fListPage = 0;
        dispFiles(fListPage);
      } else {
        String s;
        if (dirName != "") s = dirName + "/" + fileName;
        else s = "/" + fileName;
        openFile(s);  // into opening files.
        openMenu = false;
        mode = 1;
      }
    }
    if (intS.equals("279166")) {  // DOWN at file-choosing
      if (chosenFile < filesCount - 1) {
        ChosenMark(0);
        chosenFile++;
        if ((chosenFile % fnLs) == 0) dispFiles(++fListPage);
        ChosenMark(1);
        dispCurFname(fileNames[chosenFile]);
      }
    }
    if (intS.equals("279165")) {  // UP at file-choosing
      if (chosenFile > 0) {
        ChosenMark(0);
        chosenFile--;
        if (fListPage > 0 && chosenFile % fnLs == fnLs - 1) dispFiles(--fListPage);
        ChosenMark(1);
        dispCurFname(fileNames[chosenFile]);
      }
    }
  } else {                    // "openmenu == false" editing mode
    if (intS.equals("27")) {  // ESC -> return "dir files"
      openMenu = true;        // staying file-choosing mode
      mode = 0;
      clsTextArea(dirName);
      listupFiles(dirName);
      dispFiles(fListPage);
    }
    if (mode == 0) {  // at editing filename
      if ('!' <= intC && intC <= '~') fileName = fileName + String((char)intC);
      if (intC == 8) fileName = fileName.substring(0, fileName.length() - 1);
      if (intC == 127) fileName = "*.txt/*.c/*.cpp";
      dispCurFname(fileName);
    } else {                                  // mode == 1    to Editing content lines
      if (intS.equals("277983")) saveFile();  // F4 Save file
      if (intC == 127) {                      // DELETE Key
        if (cuX[line] < txt[line].length())
          txt[line] = txt[line].substring(0, cuX[line]) + txt[line].substring(cuX[line] + 1);
        else if (cuX[line] == txt[line].length())
          ShiftLines_Up(line);
      }
      if (intC == 8) {        // BACKSPACE Key
        if (cuX[line] > 0) {  // When any word exists, delete one char.
          txt[line] = txt[line].substring(0, cuX[line] - 1) + txt[line].substring(cuX[line]);
          spc[line] = spc[line].substring(1);
          cuX[line]--;
        } else if (cuX[line] == 0 && line > 0) {  // delete a line
          cuX[line - 1] = txt[line - 1].length();
          spc[line - 1] = "|";
          for (uint16_t j = 0; j < txt[line - 1].length(); j++) spc[line - 1] = " " + spc[line - 1];
          ShiftLines_Up(line - 1);
          line--;
        }
      }
      if (intS.equals("279168")) {  // LEFT
        if (cuX[line] > 0) {
          spc[line] = spc[line].substring(1);
          cuX[line]--;
        } else {
          if ((line - lb) > 0) {
            drawEditLine(0, line);
            line--;
            if (lb > 0) Redraw_OverLines(0);
          }
        }
      }
      if (intS.equals("279167")) {  // RIGHT
        if (spc[line].length() <= txt[line].length()) {
          spc[line] = " " + spc[line];
          cuX[line]++;
        } else {
          if (line < lastline) {
            drawEditLine(0, line);
            line++;
            spc[line] = "|";
            cuX[line] = 0;
            if ((line - lb) >= maxDispLines) Redraw_OverLines(1);
          }
        }
      }
      if (' ' <= intC && intC <= '~') {  // Ascii char
        txt[line] = txt[line].substring(0, cuX[line]) + (char)intC + txt[line].substring(cuX[line]);
        spc[line] = " " + spc[line];
        cuX[line]++;
      }
      if (intC == 9) {  // TAB
        txt[line] = txt[line].substring(0, cuX[line]) + "  " + txt[line].substring(cuX[line]);
        spc[line] = "  " + spc[line];
        cuX[line] += 2;
      }
      if (intS.equals("279165")) {  // UP at Editing text
        if ((line - lb) > 0) {
          drawEditLine(0, line);
          line--;
          if (lb > 0) Redraw_OverLines(0);
        }
      }
      if (intS.equals("279166")) {  // DOWN at editing
        if (line < lastline) {
          drawEditLine(0, line);
          line++;
          if ((line - lb) >= maxDispLines) Redraw_OverLines(1);
        }
      }
      if (intC == 13) {                               // RETURN at editing text
        for (uint16_t i = lastline; i > line; i--) {  // shifting next lines >= line+1
          ShiftLine(i + 1, i);
          drawEditLine(0, i + 1);
        }
        lastline++;
        if (cuX[line] > 0) {     // when "enter" at line middle, separate a line two.
          String t = txt[line];  // at line end, new line.
          txt[line] = t.substring(0, cuX[line]);
          txt[line + 1] = t.substring(cuX[line]);
          spc[line] = spc[line].substring(0, cuX[line]) + "|";
          spc[line + 1] = "|";
          cuX[line + 1] = 0;
        } else {  // when "enter" at line head,  insert a new line.
          ShiftLine(line + 1, line);
          Init_line(line);
        }
        drawEditLine(0, line);
        line++;  // move to next line
        if ((line - lb) >= maxDispLines) Redraw_OverLines(1);
      }
      drawEditLine(1, line);
    }
  }
}
// Functions -------------------------------------
void Redraw_OverLines(bool pm) {
  if (pm == 0) lb--;
  else lb++;
  for (uint8_t i = 0; i < maxDispLines; i++) drawEditLine(0, i + lb);
}
void ShiftLines_Up(uint16_t ln) {
  txt[ln] = txt[ln] + txt[ln + 1];
  drawEditLine(0, ln);
  for (uint16_t i = ln + 1; i < lastline; i++) {
    ShiftLine(i, i + 1);
    drawEditLine(0, i);
  }
  Init_line(lastline);
  spr1.fillSprite(0);
  spr1.pushSprite(1, 35 + ((lastline - lb) * _LH));
  lastline--;
}
void ShiftLine(uint16_t a, uint16_t b) {
  txt[a] = txt[b];
  spc[a] = spc[b];
  cuX[a] = cuX[b];
}
void Init_line(uint16_t i) {
  txt[i] = "";
  spc[i] = "|";
  cuX[i] = 0;
}
void clsTextArea(String fn) {
  dispCurFname(fn);
  lcd.fillRect(1, 27, SW - 1, SH - 27, TFT_BLACK);
  line = 0;
  lastline = 0;
  lb = 0;
  for (uint16_t i = 0; i < maxTextLines; i++) Init_line(i);
}
void listupFiles(String dirName) {
  if (dirName.equals("") || dirName.equals("/")) dirName = "/";
  File root = SD_MMC.open(dirName);
  filesCount = 0;
  if (!root.isDirectory()) {
    return;
  }
  File file = root.openNextFile();
  while (file) {  // Store the file name in the array
    if (filesCount < maxFiles) {
      String fn = file.name();
      fn.toLowerCase();
      if (file.isDirectory()) fn = fn + "/";
      fileNames[filesCount] = fn;
      filesCount++;  // Increment file counter
    }
    file = root.openNextFile();  // Move to the next file
  }
}
void saveFile() {
  String ff = "/" + fileName;
  File file = SD_MMC.open(ff, FILE_WRITE);  // Open file in write mode
  if (file) {                               // Write
    for (uint8_t i = 0; i <= lastline; i++) file.println(txt[i]);
    file.close();
    Serial.println(F("File save successfully."));
  }
}
void openFile(String s) {
  Serial.println("Trying read " + s);
  File fp = SD_MMC.open(s, FILE_READ);
  if (strstr(s.c_str(), ".bmp")) {
    lcd.drawBmp(&fp, 1, 26);  //  if available
  } else if (strstr(s.c_str(), ".png")) {
    lcd.drawPng(&fp, 1, 26);
  } else if (strstr(s.c_str(), ".jpg")) {
    lcd.drawJpg(&fp, 1, 26);
  } else {
    clsTextArea(s);
    lastline = 0;
    while (fp.available()) {
      uint8_t c = fp.read();
      if (c == 10) lastline++;  // Increment the line count
      if (lastline == maxTextLines - 1) break;
      if (c == 9) txt[lastline] += "\t";  // Horizontal Tab
      if (c >= 32 && c <= 126) txt[lastline] += (char)c;
    }
    fp.close();                                 // Close the file
    for (uint16_t l = 0; l <= lastline; l++) {  // make background spc
      if (l == maxTextLines - 1) break;
      cuX[l] = txt[l].length();
      spc[l] = "|";
      for (uint16_t j = 0; j < txt[l].length(); j++) spc[l] = " " + spc[l];
      drawEditLine((l == 0) ? 1 : 0, l);
    }
    line = 0;
    Serial.println(F("File read successfully."));
  }
}
void dispFiles(uint8_t page) {
  lcd.fillRect(1, 26, SW - 1, SH - 26, TFT_NAVY);
  lcd.setTextColor(TFT_YELLOW);
  for (uint8_t i = 0; i < fnLs; i++) {
    if (i + page * fnLs < filesCount) {
      char s[16];
      sprintf(s, "%2d", i + page * fnLs);
      lcd.drawString((String)s + ":" + fileNames[i + page * fnLs], 30, 34 + i * _LH);
    }
  }
  ChosenMark(1);
  dispCurFname(fileNames[chosenFile]);
}
void ChosenMark(bool c) {
  if (c == 0) lcd.fillRect(15, 38 + (chosenFile % fnLs) * _LH, 10, 10, TFT_NAVY);
  else lcd.fillRect(15, 38 + (chosenFile % fnLs) * _LH, 10, 10, TFT_YELLOW);
}
void drawEditLine(bool _d, uint16_t ln) {
  if (ln < 0) return;
  if (_d) {              // == 1 then draw cursor
    spr1.fillSprite(1);  //フォーカス行の背景は少し明るく
    spr1.setTextColor(3);
    spr1.drawString(spc[ln], 33, 2);  // "|"を先に表示
  } else spr1.fillSprite(0);
  String n = (ln + 1 < 10) ? "00" : ((ln + 1 < 100) ? "0" : "");
  spr1.setTextColor(2);
  spr1.drawString(n + String(ln + 1) + ">", 1, 2);  // 行番号
  spr1.setTextColor(4);
  spr1.drawString(txt[ln], 33, 2);
  spr1.pushSprite(1, 35 + (ln - lb) * _LH);
}
void dispCurFname(String fn) {
  spr0.fillSprite(0);
  spr0.setTextColor(1);
  spr0.drawString(fn, 2, 3);
  spr0.pushSprite(51, 1);
}

 最後まで見ていただきありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?