[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[FDclone-users:00943] Re: ツリーで移動中にSEGV



 しらいです。

In Message-Id <20120229115318.1AC5887C001@yuka.unixusers.net>
        Takashi SHIRAI <shirai@unixusers.net>writes:
>  しらいです。

>  時間が掛かりそうなので Ack だけ返しておきます。FDclone の
> source code 見るのは一年ぶりくらいですか。

 お待たせしましたがようやく直すことが出来ました。


>  出来れば本家の挙動に合わせて実装したいんですが、MS-DOS の
> 稼働環境が既に...。

 patch は巻末に添付するとして、結局この本家の挙動に関して先
に解説しておきます。


 頑張って MS-DOS 環境を用意して本家の挙動を紐解き、それに合
わせた仕様にしましたので、今回の bug fix に留まらない修正に
なっています。
 本家の実装では、tree 行数が画面行数以内の場合には PageUp
も PageDown も無視されます。なので、これを踏襲するには tree
行数を知っておく必要があります。

 FDclone では本家の実装と異なり、directory 探索時間を省くた
めに directory の折畳みを行なった tree 表記を採用しています。
つまりこの折畳みを展開しないと行数は判りません。
 下位 directory を折畳んだ「>」付の directory に関しては、
元々 cursor 移動では展開されない仕様なので、PageUp/PageDown
でもそのままにしておきます。
 問題は「その他」としてまとめられた「...」表記の directory
です。こちらはその位置に cursor を持っていくことで展開される
ので PageUp/PageDown でも対応が必要です。

 ここで二つの実装が考えられます。一つは展開前に行数のみ調べ
て PageUp/PageDown の有効性を確認する方法で、もう一つは実際
に展開してしまってから行数を調べる方法です。
 前者の場合、無効だった場合にはキー押下の前後で状況が何も変
わらないので、本家の挙動に忠実だと言えますが、折畳まれたまま
の状態では何故無効なのか利用者に伝わりにくいと思います。
 後者の場合、無効だった場合には scroll はしないのに折畳み部
分の展開のみ遂行されるという気持ち悪さは残りますが、展開して
なお行数不足であることが利用者に伝わると思います。

 どちらの実装も試してみたのですが、前者は存外に多くのコード
を必要とする割には、特にメリットと呼べる程の優位性が無く、無
駄なことをしているだけのように感じました。
 ということで添付の patch では後者の実装を採用しています。
もし異論のある方がいるようでしたら再考しますので、release ま
でに意見を下さい。


 尚 release 時期に関してですが、一年以上も溜め込んでいただ
けに他にも幾つか未発表の bug fix を含んでいます。そのため、
platform 別の検証に幾分時間がかかると思います。
 折角環境を用意したので MS-DOS 版でもじっくりと検証を行ない
たいところですが、これがまた遅くて往生しております。VM 上に
しかない MINIX も結構な遅さです。
 今月中には release 出来ればと思っていますが、余り期待せず
に待って頂けると幸いです。それまでは取り敢えずこの patch で
凌いで下さるようお願いします。


---- Cut Here ----
diff -ur ../old/FD-3.00j/tree.c ./tree.c
--- ../old/FD-3.00j/tree.c	Sat Sep 25 00:00:00 2010
+++ ./tree.c	Fri Mar  9 17:24:57 2012
@@ -36,6 +36,7 @@
 static int NEAR treeup __P_((VOID_A));
 static int NEAR treedown __P_((VOID_A));
 static int NEAR freetree __P_((treelist *, int));
+static int NEAR bottomtree __P_((VOID_A));
 static VOID NEAR _tree_search __P_((VOID_A));
 static int NEAR _tree_input __P_((VOID_A));
 static char *NEAR _tree __P_((VOID_A));
@@ -556,6 +557,24 @@
 	return(n);
 }
 
+static int NEAR bottomtree(VOID_A)
+{
+	int min, oy, otop;
+
+	min = filetop(win);
+	oy = tr_line;
+	otop = tr_top;
+	while (tr_line < min + FILEPERROW - 2) if (treedown() < 0) break;
+	if (tr_line >= tr_bottom - 1 && tr_top >= min + 1) {
+		tr_line = oy;
+		tr_top = otop;
+		searchtree();
+		return(-1);
+	}
+
+	return(0);
+}
+
 static VOID NEAR _tree_search(VOID_A)
 {
 	int oy, otop;
@@ -595,23 +614,20 @@
 			treedown();
 			break;
 		case K_PPAGE:
+			if (bottomtree() < 0) break;
 			half = (FILEPERROW - 1) / 2;
-			tmp = min + half + 1 - tr_line;
+			tmp = min + half + 1;
 			if (tr_top + half > min + 1) half = min - tr_top + 1;
 			if (half > 0) tr_top += half;
-			for (;tmp > 0; tmp--) if (treedown() < 0) break;
-			tr_line += tmp;
+			tr_line = tmp;
 			searchtree();
 			break;
 		case K_NPAGE:
+			if (bottomtree() < 0) break;
 			half = (FILEPERROW - 1) / 2;
-			tmp = half + (min + half + 1) - tr_line;
-			while (tmp-- > 0) if (treedown() < 0) break;
-			tmp = tr_line - (min + half + 1);
-			tr_line = min + half + 1;
-			if (tr_bottom - tmp < min + FILEPERROW - 1)
-				tmp = tr_bottom - min + FILEPERROW + 1;
-			tr_top -= tmp;
+			tmp = min + half + 1;
+			while (half-- > 0) if (treedown() < 0) break;
+			tr_line = tmp;
 			searchtree();
 			break;
 		case K_BEG:
@@ -676,6 +692,7 @@
 		case K_BS:
 			do {
 				if (treeup() < 0) break;
+				if (!tr_cur || !(tr_cur -> sub)) break;
 			} while (&(tr_cur -> sub[tr_no]) != old);
 			break;
 		case 'l':
---- Cut Here ----

                                               しらい たかし