2008年5月31日土曜日

第96回目 QXマクロの紹介(その7)

○第96回目 QXマクロの紹介(その7)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデータ以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 今回はこれを取り上げます。
 9.この文書の全文を別の文書のある部分にコピーしたい
 10.この文書のこの部分を別の文書のある部分にコピーしたい

 QXエディタはタブ形式です。ですから複数のファイルを一つのウィンドウで同時に開いておくことが出来ます。

 あるファイルのすべてを、別のファイルのカーソルのある位置にコピーします。トランザクションを別のファイルで作っておいて、完成後、メインのマスターに追加するという感じの処理というのでしょうか。

 意外とこれがスムーズに運びストレスを感じません。
 通常の作業で行なうと、
 1.Ctrl+A  すべてを選択
 2.Ctrl+C  コピー
 3.Ctrl+W(該当するウィンドウに移る。QXでは常に二つのウィンドウを認識している。それ以外の別のファイルへの移動は、Alt+W+番号となります)
 4.Ctrl+V  貼り付け
 です。
 これが同じ条件で、
 TAB+Aで終ります。(ショートカットキー化されています)

 本当に必要なのは一部をコピーすることだともいますが、これも比較すると
 範囲を指定し、TAB+X
 で終ります。(ショートカットキー化します)

 前者は後者に含まれますので、最終的には一つのマクロとなります。
 範囲が選択されていない=⇒全文コピー
 範囲が選択されている =⇒その範囲をコピー

 現在は、用途の関係から、それぞれ別マクロとし、更に後者を更に分けています。
 つまり、後者のほうを、
 範囲が選択されていない=⇒特殊記号に挟まれた部分をコピー
 範囲が選択されている =⇒その範囲をコピー
 としています。
 これは、辞書的なファイルを作っている関係から必要となったものです。
 一つの項目が○から始まり、次の○の直前で終わる。
 これを単位として、コピーするというものです。
 コピーしたい範囲内にカーソルがあれば実行できるので、非常に便利です。
 気持ちよくいく、という感性的な快感を重要視したものです。

 では単純な全コピーから。
if @hwnd = 0 then exit proc
@BlockSelectAll
@BlockClipboardCopy
@WindowChange 'QXエディタで現在認識されている別のファイルに移動
@BlockClipboardPaste
 でおしまいです。
 直前に表示されていたウインドのカーソルのあるところにコピーされます。

 では後者の場合です。
 まずは選択されているかどうかの判断です。
 '選択されているかどうかを取得
sel_md=@Select '0は選択されていません。
if sel_md=0 then

 選択されている場合は、
@BlockClipboardCopy 以下を実行すればいいことになります。

 選択されていない場合は、
 範囲を指定して、
@BlockClipboardCopy 以下を実行すればいいことになります。

 範囲指定は…。
 頭は、
'区切り語を上に向かって検索する。
@@FindAddString "^" & rr$,0  'rrは○です。"^"が付くことで先頭のものだけを検索します
@SearchRepeatUp
if @@SearchFound=0 then exit proc
'ブロック選択開始
@BlockSelect
 最後は、
'区切り語を下に向かって検索する。
@@FindAddString "^" & rr$,0
@SearchRepeatDown
'区切り語がなかった場合、行末にいく
if @@SearchFound=0 then
@MoveFileBottom
@MoveBeginningLine
end if
'クリップボードにコピー
@BlockClipboardCopy
 と続きます。

 感覚的に、操作がスムーズにいったという感じが必要だと思います。そのとおりの感じを受けるはずです。
 
 次に、機能拡大をすべき事項は、ウィンドウの選択です。現在は、直前表示されていたウィンドウに対して張り付けるということですが、これを、任意のウィンドウに、任意のカーソルの場所に貼り付けられるということです。
 いろいろ研究した結果、それほど難しくはないことがわかりました。
 次回、確認の結果、整理して紹介します。

※今回紹介したのは一つのかたちです。やっていくともっとということになり、それに対応していくと更に便利になります。
 考えられるアイデアとしては、区切り記号を入力するようにすることです(一部をメニュー化し、それ以外は入力することも考えられる)。これによって一つのエクセルマクロを簡単な操作でクリップボードにコピーすることができます(区切り記号はSubとなる。その後の操作は、エクセルのモジュールのウィンドウに移動して、Ctrl+Vで貼付けてください)。

2008年5月25日日曜日

第95回目 QXマクロの紹介(その6)

○第95回目 QXマクロの紹介(その6)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 8.複数の行のある位置に同じ文字列を挿入したい
 この機能もよく使います。
 特にマクロを作っているときに、デバック用に一時的にコマンド群を作ります。そしてチェックが終わるといらないのですが、後で何かの役に立つかということで、コメント分として残しておきます。また、あるマクロを元に新しいマクロを作るときなど、必要かもしれないというコマンド群をコメントとして残しておくことがあります。
 そのようなときに威力を発揮します。筆者は、コメント文にするというマクロと、それを通常のコマンドに直すというマクロを作っています(文頭に"'''"をつける、取るというマクロです)。
 マクロの行下げなどにも使います(タブを行頭に追加する)。
 挿入する文字列は指定できますので、いろいろと使い勝手がいいのです。
 また、文末に挿入することも可能です。この事例もあると便利です。
 しかしながら、途中に挿入する事例はありますが、非常に定式化できずらいと思います。

 流れです。
 0.対象となる行の範囲を指定します
 1.指定した範囲の行番号を取得
 2.挿入したい文字列の入力
 3.挿入する位置の入力
 4.挿入

 1.指定した範囲の行番号を取得
 これは定番の処理です。
  '選択範囲を記憶して、選択解除
  y_begin = @SelectStartLine
  y_end = @ScrLineToCrLine(@SelectEndLine)

 2.挿入したい文字列の入力
 '文字列の入力
msg$ = "挿入したい文字列を入力してください"
rr$ = inputbox$(msg$,"QX32 行頭に文字の挿入","\t") '\tはタブのこと
if rr$ = "" then exit proc

 3.挿入する位置の入力
'文字列の入力
msg$ = "挿入したい場所を入力してください。文字数"
a1 = inputbox(msg$,"QX32 行頭に文字の挿入",0)

 4.挿入
 挿入の対象行の制御はdo loopで行ないます。
  do
  :
   @MoveNextLineCr  '次の行に進める。この行は論理行である。
  loop while @ScrLineToCrLine(@Line) < a1 =" 0" a1 =""> len(a$) then
@MoveEndLine
@InsertF rr$ '制御文字(タブ、改行など)の可能性がありますので、@InsertFを使う。
else
b$=left$(a$,a1+1)
a2=lenb(b$)
@BytePosCr = a2
@InsertF rr$
end if
end if

 今回はここまで

2008年5月17日土曜日

第94回目 QXマクロの紹介(その5)

○第94回目 QXマクロの紹介(その5)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 削除の機能です。
 どの機能が必要かと思われますか。
 15、16あたりではないでしょうか(第90回参照)。
 15.一字一字削除していくのではなく、何文字か一気に削除できないか
 16.文末まで削除したい=⇒QXエディタの基本機能
 17.一行を簡単に削除したい=⇒QXエディタの基本機能
 18.何行かを一気に削除したい

 ワードでも、16は機能化されていますので、15を取り上げます。
 削除するとは…
 通常はその最初の場所にカーソルをもって行き、Delキーを必要なだけ押す、ということでしょう(範囲を設定してDelキーという方法もありますが、行をまたぐ大量の削除でなければ、それほどかわりません)。
 削除する文字数は最初からわかりますか?このあたりという感じは持っていたとしても、文字数はということになるとわからないのが普通ではないでしょうか。
 文字数を入力してEnterキーを押すというのは、一瞬時間が止まります。
 これをデメリットと考えるか、ワンタッチで処理が終了するのをメリットと捉えるか。
 これはいくら考えても解決しません。それほど大変ではないので、考えるよりは、作って好きなほうを使うという態度にしたらどうでしょうか。
 メリット面を生かすように、すでに初期値として何らかの数値が与えられている、としましょう。もし違っていたら…。道は二つに分かれます。あくまでの正確な数値を入力して自動的に削除してしまうという方法。もうひとつは、とりあえずの値を入力してから、通常の削除と同様に矢印キーを動かして指定する方法。
 後者のほうが無難ですね。
 もう一つ手抜きをして、マクロの中で適当な数の文字列を事前に設定して(入力はしないということです)、矢印キーで指定範囲を変えるということにします。
 削除範囲の確定はEnterキーです。
 初期値として何文字を指定すればいいのか。これはまったくわかりません。各自の事情に応じて変えてください。
 短めの場合は、5文字あたりでしょうか。
 長めの場合は、10文字あたりでしょうか。
 とりあえず筆者は、中間を取って8文字としました。

 整理してみますと、
 マクロを起動させますと
 8文字(初期値)の文字分が選択されています。EnterかDelキーを押すとその部分が削除されます。
 終わりの場所を変えたい場合は矢印キーで範囲を変えて、決まったところでEnterかDelキーを押す。
 という操作になります。
 このマクロでは文字列だけではなく、複数行も削除できます。
 ここまでくるとメリットが見えてきそうです。

 流れです。
 1.マクロを動かすと、カーソルのある文字から8文字が選択される。
 2.矢印キーで削除したい終わりにカーソルを移動する。
 3.範囲を確定し削除する。

 1.マクロを動かすと、カーソルのある文字から8文字が選択される。
'削除文字列の指定
@BlockSelect
FOR i=1 to p2  'p2には8を入れている
@MoveRightChar
next

 2.矢印キーで削除したい終わりにカーソルを移動する。
 これは前回の4.を参照してください。必要なキー操作だけ残してください。

 3.範囲を確定し削除する。
   do
   if iskeypressed(KEY_RETURN) or iskeypressed(KEY_SPACE) or iskeypressed(KEY_DELETE) then
   exit do
   elseIf iskeypressed(KEY_PRIOR) then
     :
     :
   end if
   loop while 1

   @BlockDelete

 こんな感じで終了です。
 有効なキーとしては矢印キーのほかに、Home、End、PageUp、PageDown、Tab(単語単位左へ)、BackSpace(単語単位右へ)あたりを、そろえておけばいいのではないでしょうか。
 よくわからないのですが、下矢印キーを1回押すと、その行全体が削除されます。
 上矢印キーを1回押すと、その行の上の行全体が削除されます。
 もっと続けると複数行が削除できます。
 これの変形で、下矢印キーをN回押す、左矢印キーを1回押すと、最初にあった文字から複数行が削除されます。これは最初にあった文字の前の部分は残るということです。

 ということで、複数行の削除まで出来てしまいました。
 PageUp、PageDownでは、7行分の指定が出来ますから、大きな範囲の削除も確認しながら簡単に出来ます。

 ※同一行の場合をよく使っています。使ってみて一言。
 結構便利です。ピタッとはまる時は感激します。

2008年5月10日土曜日

第93回目 QXマクロの紹介(その4)

○第93回目 QXマクロの紹介(その4)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 機能の拡張から根本的な改良
 1.前の文が短すぎて、入力で指定した位置に文字がない(本来は入力誤り)、カーソルの位置に文字がない(本来は指定誤り)の場合の処理が一つ考えられます。
 2.コピーもとの文字列を、直前の行だけでなく、当該行、直後の行も指定できる。更に、直前直後の行ではなく離れた行も指定できる、ということも考えられます。

 本質的な機能は後者です。前者は注意して入力すれば回避できますから。
 後者は、行の指定ですので、これまでは一行前だったので、最初の行のマイナス1でしたが、ここを変えればいいのです。最初の行を0として、前はプラスの数値、あとはマイナスの数値としていますので、
  前回の中で、
 『前の行の全文字列取得は、
  @Line = @CrLineToScrLine(y_begin-1) '論理行から物理行への変換
  b$ = @TextCr$(@Line)』
 としていましたが、(y_begin-1)の"1"を、入力したものにすればいいのです。
 これで終了です。

 簡単すぎてばかばかしいほどです。

 この機能を使って作業をしていますと、やはりこれもあれもということになっていきます。そして現時点の最終形は、最も簡単(マクロ構造上)なものに集約されてしまいました。
 基本的な違いは、カーソルの動きを主にしたことと、移動も加えたことです。
 前者の意味は、コピー元をカーソルを動かして先頭も最後も決定するということです。すべてカーソルを動かすのではなく、おおよその行の位置を入力します。入力値は第一次のカーソルの移動という意味合いとなります。その後にコピー元を決定しますので、間違った行であってもいいのです。(移動はコピーの変形なので詳細は省略)

 マクロの流れを追っていきます。
 1.カーソルの場所、行を取得する。最終的にはここに貼り付けます。
 2.およその行の入力。(移動の場合は頭に"*"をつけます)
 3.指定された行へカーソルを移動。横の位置は最初の位置のままとします。
 4.矢印キー等でコピー文の最初と最後を選択。選択はEnterとSpaceキーを使います。 矢印キーの外には、Home、End、PageUp、PageDown、Tab(単語単位左へ)、BackSpace(単語単位右へ)が使えます。
 5.コピー文をクリップボードに貼り付ける。(移動の場合は削除してクリップボードに張り付ける、ということが異なる)
 6.元の場所に戻ってクリップボードから貼り付け。

 1.カーソルの場所、行を取得する。
'カーソル行及び場所(バイト数)を記憶
y_begin = @ScrLineToCrLine(@Line) '物理行から論理行への変換
p1=@BytePosCr
 2.およその行の入力。(移動の場合は頭に"*"をつけます)
 入力値は、コピーの場合は、2、-2、移動の場合は*2、*-2。2は2行上、-2は2行下
 (入力値がヌルの場合は、コピー機能・当該行の選択とします)
 初期値は0、コピー機能・当該行の選択としました。
msg$ = "おおよその行を入力してください。移動の場合は頭に"*"をつける"
kubun$ = inputbox$(msg$,"QX32 指定文字列のコピー・移動","0")
if kubun$ = "" then
kubun$ = "1"
p3 = 0
else
p2 = instr(kubun$,"*")
if p2 = 0 then
p3 = val(kubun$)
kubun$ = "1"
ELSE
p3 = val(mid$(kubun$,p2+1))
kubun$ = "2"
end if
end if

 3.指定された行へカーソルを移動。横の位置は最初の位置のままとします。
'カーソルの大まかな移動
@Line = @CrLineToScrLine(y_begin-p3)
@BytePosCr=p1

 4.矢印キー等でコピー文の最初と最後を選択。選択はENTERとSpaceキーを使います。 矢印キーの外には、Home、End、PageUp、PageDown、Tab(単語単位左へ)、BackSpace(単語単位右へ)が使えます。
 4-1.使用するキーの指定
'キーの設定
call iskeypressed(KEY_RETURN)
call iskeypressed(KEY_SPACE)
call iskeypressed(KEY_PRIOR) '行を上に画面単位で移動
call iskeypressed(KEY_NEXT) '行を下に画面単位で移動
call iskeypressed(KEY_LEFT) '左矢印キー
call iskeypressed(KEY_UP) '上矢印キー
call iskeypressed(KEY_RIGHT) '右矢印キー
call iskeypressed(KEY_DOWN) '下矢印キー
call iskeypressed(KEY_END) '文末
call iskeypressed(KEY_HOME) '文頭
call iskeypressed(KEY_TAB) '単語単位に左に移動
call iskeypressed(KEY_BACK) '単語単位に右に移動
4-2.押されたキーによってカーソルを動かすなど
 押されたキーによって処理をする。
 マクロ中ですので通常のキー操作が効きませんので、押されたキーをもとにキー操作をマクロで作ります。
 確定は2回行ないますので、その区分をするためにフラッグを立てます。1回目は選択開始、2回目は選択の終了で、doループを抜け出して次の処理へ行きます。Spaceキーで文字を変換する操作になれているので、EnterキーのほかにSpaceキーでも可能としました。
 基本的には無限ループなので、CPUが使いっぱなしなってしまいます。途中に動きを止める命令(_sleep(50))を入れています。50とは1000分の50秒のことです。
 if文の後にあるコマンドは、QXマクロでのキー操作コマンドです。@MoveRightCharはカーソルを右に動かすコマンドです。
flag = 0
do
call _sleep(50)
if iskeypressed(KEY_RETURN) or iskeypressed(KEY_SPACE) then
if flag=1 then exit do
flag=1
@BlockSelect
elseIf iskeypressed(KEY_PRIOR) then
@ScrollUpHalfPage
elseif iskeypressed(KEY_NEXT) then
@ScrollDownHalfPage
elseif iskeypressed(KEY_LEFT) then
@MoveLeftChar
elseif iskeypressed(KEY_UP) then
@MoveUpChar
elseif iskeypressed(KEY_RIGHT) then
@MoveRightChar
elseif iskeypressed(KEY_DOWN) then
@MoveDownChar
【以下略】
end if
loop while 1
 5.コピー文をクリップボードに貼り付ける。(移動の場合は削除してクリップボードに張り付ける、ということが異なる)
 コピーか移動かはkubun$で判断します。
'指定範囲をクリップボードへ、クリックからコピー
if kubun$ = "1" then
@BlockClipboardCopy
else
@BlockClipboardCut
end if

 6.元の場所に戻ってクリップボードから貼り付け。
@Line = @CrLineToScrLine(y_begin)
@BytePosCr=p1
@BlockClipboardPaste

※比較
通常の操作(カーソルは貼り付けたい場所にある状態から。コピーもとが五行上にあったとする)
 1.カーソルを五行上に移動
 2.カーソルをコピー文の先頭に移動
 3.シフトを押しながらカーソルをコピー文の最後に移動
 4.Ctrl+Cでクリップボードへ
 5.カーソルを貼り付けたい場所に戻す。1と2の操作
 6.Ctrl+Vでクリップボードから貼り付け

 このマクロによる操作
 1.マクロの起動。TAB+1の2タッチ
 2.パラメータの入力。5と入力。
 3.入力値の確定。Enterキーを押す
 4.カーソルをコピー文の先頭に移動しEnterキーを押す
 5.カーソルをコピー文の最後に移動しEnterキーを押す

 共通部分を除いてみます。
通常の操作
 1.カーソルを五行上に移動
 3.シフトを押しながら
 4.Ctrl+Cでクリップボードへ
 5.カーソルを貼り付けたい場所に戻す。1と2の操作
 6.Ctrl+Vでクリップボードから貼り付け

 このマクロによる操作
 1.マクロの起動。TAB+1の2タッチ
 2.パラメータの入力。5と入力。
 3.入力値の確定。Enterキーを押す
 4.Enterキーを押す
 5.Enterキーを押す

 Ctrl+C、Ctrl+Vを2タッチとし、同数のキー操作を削除すると残るのは、

通常の操作
 1.カーソルを五行上に移動
 3.シフトを押しながら
 5.カーソルを貼り付けたい場所に戻す。1と2の操作

 このマクロによる操作
 4.Enterキーを押す
 5.Enterキーを押す

 通常操作では、1の操作が不要な場合もありますのでこの分を差し引いて、このマクロの効果としては、おおむね通常の操作の3、5が省略されるということといえます。

※掲載までの間での修正
 行数の入力をやめて、"3"を押すことによって3行移動させました。他の行数は面倒なので設定していません。
 2.パラメータの入力。5と入力。
 3.確定。Enterキーを押す
 の箇所が、
 3と上矢印と上矢印となります。キータッチとしては一つ増えました。また、下への場合は"-"を押す必要があるので、2タッチの増加です。しかしながら、感覚的に見て、こっちのほうがやりやすいようです。
 上矢印を5回押すよりも、3回(3と上矢印と上矢印)のほうが早いという主張です。
 質問
 なぜ3回なのか。=⇒PageUpでは7行動きます。真ん中で3か4かと考え、後は適当に3に決めました。
 3だけでなく、4、5、6も対象にしたらどうか。=⇒取り入れてみましょうか。1-9まで可能とします。

2008年5月4日日曜日

第92回目 QXマクロの紹介(その3)

○第92回目 QXマクロの紹介(その3)
 ※QXマクロは、QXエディタ(テキストエディタ)で使用されるマクロのことです。
  QXマクロでは、全角スペースはデーター以外は認められていません。コピーして使う場合は、必ず半角スペースに変えてください。

 文章作成の効率を若干上げるマクロです。
 今回は、
 3.前の行のあの部分をコピーしたい
 を取り上げます。
 文字列の場所の指定としては、2-10(この10は文字数)、-10、15-、ここまでは普通でしょう。
 更に、0、0-12、0--10、99-10という指定もできるようにしています。
 0って?=⇒現在のカーソルの位置を基準として末尾までという指定です
 0-12って?=⇒現在のカーソルの位置を基準として後ろに12文字という指定です
 0--10って?=⇒同じく、現在のカーソルの位置を基準として前に10文字という指定です
 99-10って?=⇒文末から前に10文字という指定です
 (前の行が現在のカーソル位置よりも短い場合は、更に行を前にさかのぼっていって、その位置に文字がある行からコピーするようにしていますが、この講では、出来るだけ単純にするために、該当する文字列がなしとして、何もコピーしないことにします。)
 このマクロで問題になったのは、現在のカーソルの位置が、前の行の文字の位置とぴったり重なっていない可能性があるということです。半角全角が混じっていると、うまくぴったりあわないことがあります。
 それ以外の場合は、文字列の切り出し関数、mid$で開始文字数とコピーする文字数を指定すれば、簡単にコピーもとの文字列は取得できます。挿入する場所はカーソルのある場所の前になっているので、そのままま挿入すればいいことになります。
 これも、前回同様に処理の流れを見てみましょう。

 1.コピーしたい文字列の場所を入力する
 2.前の行を変数に取得する
 3.入力値を分解する
 4.位置の指定、カーソル位置からの指定、末尾からの指定ごとに処理を行なう。
  =前の行から文字列を切り出し、コピーする。

 1.コピーしたい場所を入力する
 msg$ = "コピーしたい文字列の範囲を入力してください。5-20、8-、-25、0、0-8、0--8、99-8"
 in_pos$ = inputbox$(msg$,"QX32 文字列のコピー","0")
 p2 = instr(in_pos$,"-")
 if p2 = 0 and in_pos$ <> "0" then exit proc
 -が含まれてなく、0でない場合は、終了とします(5と入力した場合、入力値は有効と思われますが、めんどくさかったので無効としました。1文字の場合は無理にでも、5-1のように指定をしてください)。

 2.前の行を変数に取得する
 これを行なうために、最初の行及びカーソルの位置を取得しておいてください。最初の行は論理行に変換します。
  y_begin = @ScrLineToCrLine(@Line) '物理行から論理行への変換
  p1=@BytePosCr
  前の行の全文字列取得は、
  @Line = @CrLineToScrLine(y_begin-1) '論理行から物理行への変換
  b$ = @TextCr$(@Line)
  となります。(この段階で、制御は前の行にいっていますので、貼り付ける時、もとに戻しておく必要があります)

 3.入力値を分解する
 -の位置が問題になります。これはp2に入っていますので、基本的にはその前後に分解します。前をm1、後ろをm9とします。分解した後は数字に直すことを忘れないようにしてください。m9は文字数という位置づけにします。まずは単純に分解してください。
 ただし、p2=0の場合("0"という入力の場合)は、m1は1、m9は999としておきます。
 ただし、p2=1の場合("-9"という形式)は、m1は1とします。
 ただし、p2=末尾の場合("8-"という形式)は、m9は999とします。
 (99-8の場合は、単純にm1は99、m9は8とします)

 3-2.指定値の修正
 前の行の文字数で修正します。最終的にはm1もm9も文字の位置にします。
 原則としてm9には文字数が入っていますので、m9=m1+m9-1とし、文字の位置にします。
 m1=99の場合は、m1="前の行の文字数"-m9+1とし、m9は"前の行の文字数(=位置)"とします。
 m9=999の場合は、m9="前の行の文字数(=位置)"とします。
 すると、もれるのは、カーソル位置から求める場合だけとなります。これはあとで記述。
 ただし、この結果、m1とm9が逆転していた場合は、m1とm9を入れ替えます。
 また、文字の長さをオーバーしていたとか、マイナスだったとか、文字の長さに制限する、1とするまたは処理終了(exit proc)する、とかしてください。

 4-1.位置の指定、末尾からの指定の場合
 カーソルを元の位置に戻します。
  @Line = @CrLineToScrLine(y_begin)
  @BytePosCr=p1
 コピーする文字は、
  c$=mid$(b$,m1,m9-m1+1)
 貼り付けは
  @Insert c$
  @BytePosCr=p1 'カーソルを元の場所に戻します。これはなくてもいいです。

 4-2.カーソル位置からの指定の場合
 最初のカーソルの位置を、p1=@BytePosCrで取得しています。
 前の行の文字のバイト長(lenb(b$))より、p1が大きかった場合は、処理を終了させます(exit proc)。
 p1は、カーソルのある文字が始まるバイト数となっています。頭から全角の文字列で4文字目にカーソルをおいた場合、カーソルの位置は7となります。前の行の7バイト目から始まる文字があるといいのですが、ない場合があります。最大が全角ですので、可能性は6バイト目から始まる全角文字です。(このような場合は、その文字から貼り付け対象とすることとします)
 さてさて、バイト位置と文字の位置をどうやって対応付けますか。
 1文字ずつ、そのバイト長を求めていきます。それを末尾まで行い、バイト数を累積したものを配列変数に入れます。
 これは、その文字の終わるバイト位置になっています。
 for i = 1 to len(b$)
  nn(i) = lenb(mid$(b$,i,1))+ nn(i-1)
 next
 さて、これらのバイト位置とp1を比較します。それぞれの意味合いが違うので注意を要します。
 前の例(7バイト目から始まっている)で考えて見ますと、6バイト目で終わっている文字があると、これは対象外です。次の文字はp1から始まっているということになりますから。
 順番に見て、7バイト目で終わっていた場合は、最初の文字としていいでしょう。
 順番に見て、7バイト目で終わっているものがなく、8バイト目で終わっていた場合は、7バイト目から始まっている全角の文字と判断できますので、最初の文字となります。
 順番に見て、9バイト目で終わっているものは、最大でも8バイト目から始まっているので、最初の文字とはいえません。
 したがって、初めて7バイトまたは8バイトの切れ目を持っている文字が、最初の文字となります。
for i = 1 to len(b$)
if p1 <= nn(i) then
m1=i
exit for
end if
next
次に、終わりの文字の処理です。
0-5とは、カーソルの位置以降の5文字という意味なので、
m9=m1+m9(5のこと)-1となります。(入力値を分解したものをまずm9に入れている)
0--5とは、カーソルの位置以前の5文字という意味なので、
m9=m1+m9(-5のこと)+1となります。(これは入力値がマイナスかどうかで判断できます。この結果、m1とm9が逆転しますので、入れ替えておいてください)
 m9が文字の長さをオーバーしてる場合は文字の長さにとどめておいてください。
 カーソルを戻し、文字を切り出し貼り付けるのは、4-1と同じですので省略します。

 ※機能の拡張
 前の文が短すぎて、入力で指定した位置に文字がない(本来は入力誤り)、カーソルの位置に文字がない(本来は指定誤り)の場合の処理が一つ考えられます。
 次に、コピーもとの文字列を、直前の行だけでなく、当該行、直後の行も指定できる。更に、直前直後の行ではなく離れた行も指定できる、ということも考えられます。
 ニーズいかんですが、必要性は結構あります(よ)。

 今回はここまで。