履歴
1999/2/15	最初のバージョン(シンクロ不可)。
1999/2/16	シンクロ出来るバージョン。
		誤解および無知による誤情報を訂正(お恥ずかしい…)。
1999/2/18	ファイル名(=タイトル名)が32文字以上の時、暴走するバグを修正。
		また、タイトルは最大72文字までに制限した。
		(鵜飼さん、ありがとうございました)
1999/2/26	タイトルに関するオプションを追加。

プログラム

このプログラム(makememo.exe)は、エディタ等で作成した複数のテキストファイルをまとめて、一気にTrueSync Desktopのメモ帳を作るプログラムです。頻繁にメモ帳を更新したい人、お気に入りのエディタから離れられない人(両方とも私です)は、その便利さを理解して頂けるはずです。

プログラムはここ (makememo_exe.zip)です。Windows95専用です。98でもNTでもOKのはずですが、確認してません。

(追記)Windows98でも動作する、とのレポートを頂きました。
UNZIPしてPATHの通ったディレクトリに置いて、DOS窓から実行します。

また、お試しの際はメモ帳のデータをバックアップしてからにしてくださるよう、お願いします。勝手ながら、データ消失等については責任は持てません。各自の責任において使用してください。

使い方

	makememo [-t<最大タイトル長>] [-m<タイトルモード>]
-tでメモにつくタイトルの最大長を設定します。ディフォルトは36です。

-mでタイトルの付け方を指定します。

ディフォルトは-m0です。-m1を使うと、TrueSync Desktopのメモ帳ではファイルの順番にメモが並んでますが、DataSlimに転送するときにタイトルでソートがかけられ順番が変わります。ご注意下さい。

また、あるオプションでmakememoしてシンクロして、元データを変更せずにオプションだけを変えてmakememoしてシンクロしても、DataSlim側のデータ(タイトル)は変更されないみたいです。「上書き」を指定しても駄目な模様です。シンクロのアルゴリズムが明らかになっていないので詳しい事は分かりませんが、現状では頻繁にオプションを変える事は得策ではないみたいです。ここあたりの事で悩みたくない方は、なるべくディフォルトの設定で(つまりオプションを指定せずに)使用なされる事をお勧めします。おかしくなったら、元データの日付を変える事で(touchするなり、エディタで開いて即セーブするなりして)、正常になります。

使い方の例

今使っているデータを引き継ぎたい人がほとんどでしょうから、それを前提にして解説します。

まずメモ帳データのディレクトリを作ります。ここではC:\DataSlimとします。ここに現在のフォルダーと同じ名前のディレクトリを作ります。ここではDataとNewsとします。つまり、

	C:\DataSlim--+--Data
	             |
	             +--News
と言う風になります。次にメモの内容をプレーンテキストで取り出して(コピー&ペーストもしくはリッチテキストでExportしてプレーンテキストに変換するかして)、メモと同じ名前のファイルを作り、対応するディレクトリに転送します。
	C:\DataSlim--+--Data\時刻表
	             |      \パーツ価格
	             |
	             +--News\NEWS001
	                    \NEWS002
	                    \NEWS003

後はC:\DataSlimにCDして、makememoを実行すれば、

	メモ.SKWrite
	メモ.SKNoteHeader
	メモ.SKContent
の三つのファイルがC:\DataSlimに生成されます。これをTrueSyncのデータディレクトリ(普通はC:\Program Files\Starfish\TrueSync Desktop\Userdata)に転送すると、TrueSync Desktopのメモ帳で見えるはずです。

update.batを作って、

	makememo
	move メモ.* "C:\Program Files\Starfish\TrueSync Desktop\Userdata"
とでもすれば良いでしょう。後はシンクロさせるだけです。

これ以降のメモ帳データのアップデートは、C:\DataSlimの下のディレクトリにあるテキストファイルに対してだけ行う事になります。TrueSync Desktopを使ってメモ帳を変更する事は可能ですが、その変更は次にmakememoしたときに上書きされて消えます。TrueSync Desktopのメモ帳エディタに未練がある人、およびDataSlim本体でメモを入力する人には、このプログラムはお勧めしません。すいません。

蛇足とは思いますが、このプログラムはメモ帳以外の機能(アドレス帳、To Doリスト等)には、一切影響を与えません。

フォーマット解析

これ以降の情報は、興味のない方は読み飛ばしてください。「お前の作ったプログラムぢゃ満足できん。自分で作るわい」と思われた方の参考にでもなれば、と思って書いてます。

さて、ホームページでMSをこき下ろしましたが、困ったチャンはMSだけではなくて、DataSlimを作ったStarfish(これってBorlandですよね?)も同じ。私はDataSlimをテキストビューアとして使う機会が一番多いのですが、そのメモ機能のファイルフォーマットはRich Textフォーマットであります。なんで、DataSlim本体ではプレーンテキストしか表示できないのに、こんなフォーマットを採用するのかね?

インターネットからテキストを日替わりでガバっと取ってきて、DataSlimにぶち込んで電車の中で読みたい、という使い方をするには、ファイルを全部指定してインポートするか、いちいちクリップボード経由でTrueSync desktopを使って、ファイル毎に手で転送しなけりゃならない。

この手の作業をする時に痛感するのは「GUIが使い易い」なんて言うのが単なる戯言に過ぎないという事です。「画面に出ているものを操作するだけ」っつーのは、裏を返せば「何事も画面に呼び出さなければ操作できない」って事なのにね〜。
さらに事態を悪くしてるのは、DataSlimのメモにはブックマーク機能がない事。だから、でっかいファイルに結合して転送の回数を減らそうと思うと、今度は見るときに地獄を味わう。
で、色々実験してみて分かった事は以下の通りです。
(まだ、四つのフィールドがUNKNOWNになってます。シチズンの技術者さんからの内部タレコミ情報など頂ければ、大変有り難かったりします。いや、勿論、ニュースソースは一切明かしませんとも。全て私個人の責任で処理させて頂きますので、安心して下さい。)
メモ機能は三つのファイルで管理されている。
  1. メモ.SKWrite - フォルダー構成を管理する。

    struct SKWrite {
    	WORD	numberOfFolders;	// フォルダーの総数
    	struct folderInfo f[0];		// フォルダーの総数だけ繰り返し
    }
    
    struct folderInfo {
    	char	folderName[25];		// フォルダー名
    	WORD	numberOfMemosInFolder;	// フォルダー内のメモの総数
    	WORD	currentMemoInFolder;	// 現在表示されているメモ(0 origin)
    	BYTE	unknown1;		// 不明だが0x90が書いてある
    	WORD	folderID;		// フォルダーID
    }
    
  2. メモ.SKNoteHeader - メモを管理する。
    struct SKNoteHeader {
    	char	ID[6] = "SKW300";	// ID string
    	DWORD	numberOfMemos;		// メモの総数
    	struct memoInfo m[0];		// メモの総数だけ繰り返し
    }
    
    struct memoInfo {
    	WORD	unknown2;		// 不明だが0x0010が書いてある
    	WORD	folderID;		// このメモが属するフォルダーのID
    	DWORD	createDate;		// 1970/1/1からの秒数 (time_t)
    					// メモの作成日時
    	DWORD	offsetOfMemoTitle;	// メモのタイトルのファイル内での位置
    	DWORD	lengthOfMemoTitle;	// メモのタイトルの長さ(NULLを含む)
    	DWORD	lengthOfMemoBody;	// メモの本体の長さ(NULLを含む)
    	DWORD	modifyDate;		// 1970/1/1からの秒数 (time_t)
    					// メモの変更日時
    	DWORD	unknown3;		// 不明だが0x00000000が書いてある
    	DWORD	unknown4;		// 不明だが0x00000000が書いてある
    }
    
  3. メモ.SKContent - メモの本文を格納する。

    メモ1のタイトル、本文、メモ2のタイトル、本文と言う順番で並んでいる。それぞれの頭にはフォントの指定や禁則文字の指定があり、ついでタイトルもしくは本文が続き、NULLでターミネートされている。
    0x80以上のコードや、特殊な働きを持つコードは、「\'XX」という表記になっている。

最後の難関

実はここまでの解析とコーディングは、開始から4時間ほどで終了して、TrueSync Desktopのメモ帳で見られるデータを作る事は、わりとあっさり完了したのでした。何個か手でデータを作ってmakememoして、ちゃんとシンクロ出来ます。勿論完成だと信じて疑いませんでした。

しかし、私の本当にやりたかった、「インターネットからニュースをダウンロードしてプレーンテキストに自動変換し、記事毎に自動的にぶった切って小さなファイルを沢山作り(ファイル容量制限およびブックマーク機能の欠落対策)、一気に全部メモ帳に転送する」を実現する段になって問題が出ました。別に作成してあったぶった切りプログラムの十数個の出力ファイルのうち、一部分(最初のファイルのみか、それプラス途中の一ファイル)しかシンクロ出来ないのです。TrueSync Desktopのメモ帳からは見えています。

データフィールドのうちで、不明の物が悪さしているに違いないとふんで、色々調べてみましたが、わかりません。シンクロを管理しているファイルが別にあるのかとも思いましたが、そうでもないみたいです。完全に暗礁に乗り上げました。

で、ファイルのダンプを見ているときにひらめきました。「全部タイムスタンプが同じだ……」。タイムスタンプは一秒(Windowsでは二秒)の分解能しかないため、プログラムで自動的に作成されたファイル群には、ほとんどの場合同じタイムスタンプが付いています。一つ一つtouchしてみて、再度makememo。こんどはちゃんとシンクロします。

どうやら同じタイムスタンプを持っているデータは、最初の物しかシンクロしない設計になっている模様です。手で一つ一つ入力している時には問題にはならない(とは言っても異常に入力の速い人なら起こりうるかも)のですが、自動作成のために顕在化した仕様(と言うかほとんどバグ)でした。

で、仕方なく、「メモ.SKNoteHeader」を作るときに、同じタイムスタンプを持つファイルは、タイムスタンプを一秒ずつ増加させる事にしました(あくまでも「メモ.SKNoteHeader」内のデータを加工するだけで、元のファイルのタイムスタンプには手をつけません、当然ながら)。

この修正の結果、すべてのファイルがシンクロ出来るようになりました。めでたしめでたしです。

もっとも、この修正でも、シンクロ出来なくなる場合は考える事が出来ます。例えば、

  1. 100個のファイルを一気に作る。
  2. 作った100秒以内に、
    1. makememoして、シンクロさせる。
    2. 100番目のファイルを変更する。
  3. 今変更した以外の、99個のファイルを消去する。
  4. makememoして、シンクロさせる。
この手順を踏めば、変更したファイルはシンクロされないはずです(試してはいませんが)。

まあ、こんなことは意図してやらなければ起きませんし、第一対処の仕様がないので考えない事にします。誰かいいアイデアがあったら、教えてください。


レポート等、頂ければ幸いです。

Created by Jin