にっきダイアリー

はてなダイアリーからはてなblogに移動してみました。

mixiの日記ページを再利用する

先日「窓の杜」を見てたら、mixiのデータをバックアップする「撤退!mixi」っていうフリーソフトの紹介記事があった。これを使えば今までにmixi上で書いた日記やメッセージを丸ごと保存してくれるというので、さっそくソフトをダウンロードして試してみた。
mixiにはデータのエクスポート機能なんてものはないので、撤退!mixiは日記リストページのデータを解析し、そこから日記ページを一つ一つ取得し添付画像とともに保存するようになっているらしい。
出来上がったバックアップをブラウザで見てみたら、ホントにmixiの日記ページまるごと持ってきてるのだね。ページデザインのパーツなども別フォルダにダウンロードしてあって、オンラインで見るのとほとんど同じ気分で日記を閲覧できるようになってる。
閲覧するだけならこれで充分だけど、広告から何から全部入りだから日記データとして別の何かに再利用がしにくい。
ていうかオフラインでまでこんなアクセス性の悪いオリジナルの画面のまま読みたくない!
などと思いながら配布元の説明書を読むと「XML形式で保存する」という機能もあるらしい。別のblogにインポートするならXML形式のファイルを使えと言うことなんだろう。
しかし、XML形式のファイルには日記本文だけが抜き出されていてマイミクのコメントが入っていない。他人の文章を、勝手によそで公開するとまずいという考えからそうしてるんだろうな、と、思いつつ、しかしなんだかもったいない。
ので、「撤退!mixi」がダウンロードしてくれたHTMLファイルから自分で使いやすい形式のテキストファイルを作成するスクリプトを作ってみた。
Windows版のPHP5.3で動作確認。あんまりすごいことはしてないけれど pathinfoで filename 使ってるのでたぶん5.2以降用。
PHPで作ったのはHTMLをパースするのにSimple HTML DOM Parserがすごく楽だったから、という以外にあんまり理由はない。
このスクリプトのままだと出力はMT形式で一日1ファイル。mtout関数の出力部分を変えれば他の形式で書き出せると思う。

<?php
/**
 * 撤退mixiが落としてくれた日記を読み込んでMTエクスポート用ファイルを作成する
 **/
////////////////////////////////////////////////////////////////////
define("ORG_DIR", "D:/MYHOME/MIXI/tmixi/diary/"); // 撤退mixiが作成した日記データ
define("EXP_DIR", "D:/MYHOME/MIXI/mtexp/entry/"); // MT形式にしたデータの保存先
define("IMG_DIR", "D:/MYHOME/MIXI/mtexp/image/"); // 画像の保存先
define("THM_DIR", "D:/MYHOME/MIXI/mtexp/thumb/"); // サムネールの保存先
define("IMG_URL", "./image/"); // MTでの画像の保存先
define("THM_URL", "./thumb/"); // MTでのサムネールの保存先
define("AUTHOR", "nikki"); // 自分のハンドル
define("CONTAIN_PHOTOS", true); // 写真の処理もする
define("CONTAIN_COMMENTS", true); // コメントも付ける
////////////////////////////////////////////////////////////////////

// http://simplehtmldom.sourceforge.net/
require_once("simplehtmldom_1_5/simple_html_dom.php");

date_default_timezone_set("Asia/Tokyo");

$entries = Array();
$images = Array();

if ($dh = opendir(ORG_DIR)) {
  while (($file = readdir($dh)) !== false) {
    $pinfo = pathinfo($file);
    if($pinfo['extension'] == 'html'){ // HTML
      $id = $pinfo['filename'];
      $entries[$id] = dparse(ORG_DIR . $file);
    }
    if(CONTAIN_PHOTOS){
      if($pinfo['extension'] == 'jpg'){ // 画像(JPG)
        if(substr($file, -5, 1) == 's'){ // サムネ
          echo "Copying thumbnail file: $file \n";
//          copy(ORG_DIR . $file, THM_DIR . $file);
        }
        else{
          $names = explode('_', $pinfo['filename']);
          $images[$names[0]][$names[1]] = $file;
          echo "Copying image file: $file ($names[0] - $names[1])\n";
//          copy(ORG_DIR . $file, IMG_DIR . $file);
        }
      }
    }
  }
  closedir($dh);
  
  // エントリーを書きだす
  echo "Formatting\n";
  $all = "";
  ksort($entries);
  foreach($entries as $id => $entry){
    $img = (isset($images[$id])) ? $images[$id] : false;
    $extfile = EXP_DIR . $id . '.txt';
    $all .= mtout($extfile, $id, $entry, $img);
    echo "Writing file: $extfile \n";
  }
  file_put_contents(EXP_DIR . "all.txt", $all);
  
}
else{
  echo("ディレクトリがオープンできません\n");
}

// mixiの日記ページHTMLを解析して要素を抜き出す
function dparse($file){
  $item = Array();
  echo "Parsing $file ";

  // 元ファイル読み込み;
  $str = file_get_contents($file);
  $str = mb_convert_encoding($str, 'UTF-8', 'EUC-JP');
//  $str = mb_convert_encoding($str, 'Shift_JIS', 'EUC-JP');
  $h = str_get_html($str);
  
  // タイトル
  $item['title'] = $h->find('title', 0)->plaintext;
  
  // 日付
/*
body > div#page > div#bodyArea > div#bodyMainArea > div#div#bodyMainAreaMain
 div.viewDiaryBox > div.listDiaryTitle > dl
  dt < EntryTitle and other タイトルはTITLEタグから抜き出すのでここは無視
  dd < date
*/
  // YYYY年MM月DD日hh:mm > MM/DD/YYYY hh:mm:ss
  $dstr = $h->find('div.listDiaryTitle', 0)->children(0)->children(1)->plaintext;
  $item['date'] = getdatearray($dstr);

  // 画像
/*
body > div#page > div#bodyArea > div#bodyMainArea > div#div#bodyMainAreaMain
 div.viewDiaryBox > div.txtconfirmArea > div.diaryPhoto
  table > tbody > tr
   td < photo 1〜3
*/
  // にあるけど、考えたら画像ファイルが実在するかしないかで判断すりゃいいと

  // 本文
/*
body > div#page > div#bodyArea > div#bodyMainArea > div#div#bodyMainAreaMain
 div.viewDiaryBox > div.txtconfirmArea > div#diary_body
*/
  $cont = $h->find('div#diary_body', 0)->innertext;
  $item['content'] = gettextstr($cont);

  // コメント
  $comms = Array();
/*
body > div#page > div#bodyArea > div#bodyMainArea > div#div#bodyMainAreaMain
 div#diaryComment > form#delete_comment_form > div.commentListArea
  ul
   li
    p
    dl
     dt
      a < Name href=id
      span < date
     dd < text
*/
  if(CONTAIN_COMMENTS){
    $dcomm = $h->find('div.commentListArea', 0);
    if($dcomm){
      $clist = $dcomm->children(0)->children();
      foreach($clist as $li){
        $dt = $li->children(1)->children(0);
        $comm['name'] = $dt->children(0)->plaintext; // a
        $comm['date'] = getdatearray($dt->children(1)->plaintext); // span
        $comm['text'] = gettextstr($li->children(1)->children(1)->innertext); // dd
        echo(".");
        $comms[] = $comm;
      }
      $item['comm'] = $comms;
    }
  }
  echo("\n");
  return $item;
}

// MT形式で出力
function mtout($file, $id, $entry, $images){
  $str = 'AUTHOR: ' . AUTHOR . "\nTITLE: " . $entry['title'];
  $str .= "\nBASENAME: " . $entry['date'];
  $str .= "\nSTATUS: Publish\nCONVERT BREAKS: 0\nPRIMARY CATEGORY: MIXI\nDATE: ";
  $str .= mt_getdatestr($entry['date']) . "\n-----\nBODY: \n";
  if(CONTAIN_PHOTOS && $images){
    $str .= '<p class="images">';
    foreach($images as $img => $tmp){
      $imgurl = IMG_URL . $id . '_' . $img . '.jpg';
      $thmurl = THM_URL . $id . '_' . $img . 's.jpg';
      $str .= '<a href="' . $imgurl . '"><img src="' . $thmurl . '" alt=""></a> ';
    }
    $str .= "</p>\n";
  }
  $str .= mt_gettextstr($entry['content']) . "\n-----\n";
  if(CONTAIN_COMMENTS && isset($entry['comm'])){
    foreach($entry['comm'] as $comm){
      $str .= "COMMENT:\nAUTHOR: ". $comm['name'];
      $str .= "\nDATE: ". mt_getdatestr($comm['date']) . "\n";
      $str .= mt_gettextstr($comm['text']) . "\n-----\n";
    }
  }
  $str .= "--------\n";
  file_put_contents($file, $str);
  return $str;
}

// 日時フォーマット YYYY年MM月DD日 hh:mm → YYYYMMDD-hhmm
function getdatearray($dstr){
  preg_match_all("/(\d+)/", $dstr, $d);
  $ret['y'] = $d[0][0];
  $ret['m'] = $d[0][1];
  $ret['d'] = $d[0][2];
  $ret['h'] = $d[0][3];
  $ret['i'] = $d[0][4];
  return $ret;
}

// 日時フォーマット YYYY年MM月DD日 hh:mm → MM/DD/YYYY hh:mm:00
function mt_getdatestr($m){
  return $m['m']."/".$m['d']."/".$m['y']." ".$m['h'].":".$m['i'].":00";
}

// 本文フォーマット
function gettextstr($str=""){
  $str = preg_replace("/<wbr\/>/", "", $str);
  $str = preg_replace("/ *<br \/>/", "\n", $str);
  $str = preg_replace("/\n+$/", "\n", $str);
  return $str;
}
// 本文フォーマット
function mt_gettextstr($str=""){
  $str = preg_replace("/\n/", "<br>\n", $str);
  $str = preg_replace("/(<br>\n)+$/", "\n", $str);
  $str = preg_replace("/<br>\n<br>\n/", "\n</p><p>\n", $str);
  return "<p>\n". $str . "\n</p>\n";
}

とりあえず。

追記 2011/09/12

本文やコメントの改行まわりの処理がおかしかったので修正。

データスキームを使って画像ファイルを埋め込んだimgタグを作成するクラス

以前途中まで書いて放置してたスクリプトをクラス化してみた。
あとjpeg決め打ちだったところをちゃんとファイルフォーマット調べるようにした。
キャッシュが古かったら作り直すようにした。
例外なげるのは面倒くさいのでやめた。

<?php
// base64でエンコードした画像データをIMGタグの中に埋め込んで返す
// 参考 : http://en.wikipedia.org/wiki/Data_URI_scheme

if(!defined('THUMB_CACHE_EXT')) define('THUMB_CACHE_EXT','.b64'); // キャッシュにくっつける拡張子
if(!defined('THUMB_DIR')) define('THUMB_DIR',''); // サムネールがあるディレクトリ
if(!defined('THUMB_CACHE_DIR')) define('THUMB_CACHE_DIR',''); // キャッシュを保存するディレクトリ

class DScheme {
	// データスキームキャッシュを取得
	function get_thumb_cache($tfile, $odir='', $cdir=''){
		if(!$odir) $odir = THUMB_DIR;
		if(!$cdir) $cdir = THUMB_CACHE_DIR;
		$ofile = $odir.$tfile;
		$cfile = $cdir.$tfile.THUMB_CACHE_EXT;
		$cache = NULL;
		if(file_exists($ofile)){
			$osize = getimagesize($ofile);
			if(file_exists($cfile)){
				// キャッシュの更新タイム確認
				$ostat = stat($ofile);
				$cstat = stat($cfile);
				if($cstat['mtime'] > $ostat['mtime']){
					$cache = file_get_contents($cfile);
				}
				else{
					$this->delete_thumb_cache($tfile, $cdir);
				}
			}
			if(!$cache){ // キャッシュ作成
				$cache = $this->make_thumb_cache($ofile, $cfile, $osize['mime']);
			}
		}
		return $cache;
	}

	function make_thumb_cache($ofile, $cfile, $mime){
		$bin = file_get_contents($ofile);
		$txt = base64_encode($bin);
		$cache = '';
		if($txt){
			$cache = 'data:'.$mime.';base64,'.$txt;
			fwrite(fopen($cfile, "w"), $cache, strlen($cache)); // cache保存
		}
		return $cache;
	}
	// データスキーム化したimgタグを取得
	function get_thumb_itag($tfile, $alt='', $odir='', $cdir=''){
		$itag = NULL;
		$cache = get_thumb_cache($tfile, $odir='', $cdir='');
		if($cache){
			$itag = '<img src="'.$cache.'" alt="' . $alt . '" />';
		}
		return $itag;
	}
	
	// 指定のキャッシュ削除
	function delete_thumb_cache($tfile,$cdir=''){
		if(!$cdir) $cdir = THUMB_CACHE_DIR;
		$cfile = $cdir.$tfile.THUMB_CACHE_EXT;
		unlink($cfile);
	}
}
?>
<?php 
$d = new DScheme();
echo $->get_thumb_itag('sample.jpg');
?>

Clearboxの設定とか

Clearboxのドキュメントはものすごく簡単な文章なのだけど、私の脳みそは時々どんな平易な内容でもそれがアルファベットであるというだけで「これは意味のないオサレ文字!」って認識でフリーズしてしまうことがある。
ので、脳みそが英語に対する理解力を示してくれている間にいろいろと直訳メモを書いて残しておくことにする。

使い方

HTMLソースのヘッダに

<script src="clearbox.js" type="text/javascript"></script>

と書く。
スクリプトを呼び出すときに、使いたい設定を指定できる。設定名のフォルダがclearbox/config以下にないとダメ。

<script src="clearbox.js?config=myconfig" type="text/javascript"></script>

clearbox.js には設定する項目が二つある。
CB_SrciptDir は、スクリプト一式の入ったフォルダ。clearbox.jsを読み込むhtmlファイルとの相対URL、もしくは絶対URLで指定。CB_Language は言語指定。フォルダと言語設定を指定する場合のURLはこんなかんじ。

<script src="clearbox.js?dir=scripts/clearbox&lng=ja" type="text/javascript"></script>

スクリプト内部で使っているスタイルシートなどはhtmlファイルで読み込む必要はない。

使い方

基本

lightboxなどと同様、relに「clearbox」を指定するだけ。

<a href="image.jpg" rel="clearbox" title="Caption"><img src="image_thumbnail.jpg" /></a>
ギャラリーを作成するときは以下のように[gallery=ギャラリー名]を付け加える
<a href="a.jpg" rel="clearbox[gallery=My Gallery]">sample image</a>
<a href="b.mp3" rel="clearbox[gallery=My Gallery]">sample music</a>
<a href="http://www.youtube.com/v/myrmovieid" rel="clearbox[gallery=My Gallery]">sample youtube</a>
リンク先を「inner#ほげほげ」ってやるとポップアップみたいなのも可能
<a href="inner#test" rel="clearbox">inner content</a>
HTMLタグを含めたポップアップを作りたいとき
<a href="htmlcontent" rel="clearbox[html=<strong>This is a bold text</strong>]">my webpage</a>
鍵カッコ内の書式

「パラメータ名=内容」を「,,」で区切って記述

<a href="mycontent"rel="clearbox[parameter1=value 1,,parameter2=value 2,,parameter3=value 3]">some content</a>
gallery
ギャラリー名。名称を変えれば同じページ内でいくらでも好きなだけギャラリーが作成できる。
href
You can set the url of the content with this parameter too. For example if you need to load other content than in the a tag specified.
type
メディアタイプの自動認識にまかせず、自分で指定する。指定できるのは、flash, html, iframe, image, inner, quicktime, winmedia 。
title
clearboxで表示するタイトルを指定する。指定しない場合はtitle属性を使用。
width
clearboxの表示幅指定
height
clearboxの高さ指定
tnhrf
ギャラリー専用。サムネールを指定する。作者曰く「前バージョンは tnhref だったけどeとっちゃった。ごめんね!」だそうで。
slideshowtime
これもギャラリー専用。スライドショーの時間を指定。
autoslideshow
イメージギャラリー専用。このパラメータを指定するとスライドショーが勝手に始まるよ。
comment
どのコンテンツにもコメントをつけることができる。文字数に制限はないけど、コメント表示エリアは設定ファイルで指定した高さまでしか表示されない。
closeonh
このパラメータをofにすると、背景をクリックしてもclearboxが自動的に閉じなくなる。設定ファイルにあるCB_CloseOnHの指定を上書きするよ。
dlhrf
デフォルトではダウンロードor最大表示ボタンのリンク先は表示しているコンテンツファイルだが、他のファイルをダウンロードさせたい場合はこのパラメータにURLを指定する。
dlinsame
このパラメータを指定すると、ダウンロードファイルを新しいウィンドウ(orタブ)で開く代わりに同じウィンドウで開くようになる。
html
HTMLで記述された文章を表示したいときに使う。aタグのhref要素に「htmlcontent」を指定し、このパラメータに表示したいhtmlを指定する。

他にもいろいろ使い方あるけど、省略。原文参照してください。

cb_config.js

/*
// 	ClearBox Config File (JavaScript) 
// 3.5用の設定ファイル
*/

var

// CB レイアウト:

	CB_WindowColor='#fff',				// CB window の色 (角丸用のPNG画像も変える必要があるよ!), 透明(transparent)指定もok
	CB_MinWidth=200,				// 画像の最小サイズとCB windowの初期幅
	CB_MinHeight=200,				// CB windowの初期高さ
	CB_WinPadd=15,					// CB window とブラウザ画面との隙間
	CB_RoundPix=12,					// ここを変えるなら角丸用のPNG画像も変えないとだめ。
	CB_ImgBorder=0,					// 画像のまわりに付ける枠線の幅(0で枠線なしかな)
	CB_ImgBorderColor='#ddd',			// 画像のまわりに付ける枠線の色
	CB_Padd=4,					// CB window の内側につける余白

	CB_BodyMarginLeft=0,				//
	CB_BodyMarginRight=0,				// body タグからの余白を指定する場合は
	CB_BodyMarginTop=0,				// この部分を変更すること
	CB_BodyMarginBottom=0,				//

	CB_ShowThumbnails='auto',			// サムネール表示方法 ('auto', 'always' or 'off') サムネは picture mode でしか使えないよ!
	CB_ThumbsBGColor='#000',			// サムネールの背景色
	CB_ThumbsBGOpacity=.35,				// サムネールレイヤの透明度
	CB_ActThumbOpacity=.65,				// 現在表示中画像のサムネール透明度

	CB_SlideShowBarColor='#fff',			// スライドショーバーの色
	CB_SlideShowBarOpacity=.5,			// スライドショーバーの透明度
	CB_SlideShowBarPadd=17,				// スライドショーバーの左右余白(左,右)
	CB_SlideShowBarTop=2,				// スライドショーバーの位置(画像の上辺から)

	CB_SimpleDesign='off',				// on にすると、外側の枠を表示しなくなる

	CB_CloseBtnTop=-10,				// picture mode での閉じるボタンの位置(高さ方向)
	CB_CloseBtnRight=-14,				// picture mode での閉じるボタンの位置(水平方向)
	CB_CloseBtn2Top=-20,				// content mode での閉じるボタンの位置(高さ方向)
	CB_CloseBtn2Right=-30,				// content mode での閉じるボタンの位置(水平方向)

	CB_OSD='on',					// OSD 表示
	CB_OSDShowReady='on',				// clearbox が読み込み終了になった時に OSD 表示するかどうか
							// OSDは動作テスト終わったらOFF推奨

// フォント設定:

  // タイトル文字
	CB_FontT='"MS Pゴシック" helvetica, arial, sans-serif',				//
	CB_FontSizeT=13,				// 
	CB_FontColorT='#777',				// 
	CB_FontWeightT='normal',			//

  // タイトルの下に表示されるコメント文字
	CB_FontC='"MS Pゴシック" helvetica, arial, sans-serif',				//
	CB_FontSizeC=11,				// 
	CB_FontColorC='#999',				// 
	CB_FontWeightC='normal',			//
	CB_TextAlignC='justify',			//
	CB_txtHCMax=120,				// コメント表示部分の最大高さ

  // ギャラリー名表示文字
	CB_FontG='"MS Pゴシック" helvetica, arial, sans-serif',				//
	CB_FontSizeG=11,				//
	CB_FontColorG='#aaa',				//
	CB_FontWeightG='normal',			//

	CB_PadT=10,					// 画像とタイトル表示との隙間

	CB_OuterNavigation='off',			// onにするとナビゲーションパネルが外側に表示される

	CB_ShowURL='off',				// タイトルが指定されなかった場合、タイトル部分にURLを表示する
	CB_ItemNum='on',				// ギャラリーの何番目かを表示する
	CB_ItemNumBracket='()',				// whatever you want ;)

	CB_ShowGalName='on',				// ギャラリー名を表示する
	CB_TextNav='on',				// 前の画像と次の画像へのナビゲーションを表示する
	CB_NavTextImgPrvNxt='on',			// ナビゲーションを画像で表示する
	CB_ShowDL='on',					// ダウンロードリンクを表示する
	CB_NavTextImgDL='on',				// ダウンロードリンクを画像で表示する

	CB_ImgRotation='on',				// 画像の回転メニューを表示する
	CB_NavTextImgRot='on',				// 画像の回転メニューを画像で表示する

// 元ページを覆い隠すレイヤの設定:

	CB_HideColor='#000',				// レイヤの色
	CB_HideOpacity=.9,				// 透明度 (0 で透明, 1 で完全に隠す)
	CB_HideOpacitySpeed=400,			// フェードのスピード
	CB_CloseOnH='on',				// 背景をクリックしたときにclearboxの表示を終了する

// アニメーション表示設定:

	CB_Animation='double',				// 'double', 'normal', 'off', 'grow', 'growinout' or 'warp' (CPU使います)
	CB_ImgOpacitySpeed=300,				// コンテンツのフェードスピード (ms)
	CB_TextOpacitySpeed=300,			// 文字のフェードスピード (in ms)
	CB_AnimSpeed=300,				// CB windowを変形するスピード (in ms)
	CB_ImgTextFade='on',				// 文字やコンテンツがフェードするかどうか
	CB_FlashHide='off',				// clearboxが動作する時は元ページにあるflash アニメを隠す
	CB_SelectsHide='on',				// clearboxが動作する時は元ページにある選択ボックスを隠す
	CB_SlShowTime=5,				// スライドショーで画像が切り替わる速さ (秒)
	CB_Preload='on',				// ギャラリーで表示している画像の前後の画像を先読みする
	CB_ShowLoading='off',				// NOT WORKING IN THIS VERSION (3.5beta)

// clearboxが使う画像ファイルの設定:
// (他の画像はスタイルシート内部で使ってる)
	CB_PictureStart='start.png',			//
	CB_PicturePause='pause.png',			//
	CB_PictureClose='close.png',			//
	CB_PictureNext='next.png',			// 
	CB_PicturePrev='prev.png',			//

// 上級者設定:

	CB_PicDir=CB_ScriptDir+'/config/'+CB_Config+'/pic',	// clearboxのフォルダ構成を変えた時はここも変更する

	CB_AllowedToRun='on',					// offにするとclearboxは起動しない(この設定はリロードしなくても有効)←ほかのスクリプトから操作可能ってことか
	CB_AllowExtFunctLoad='off',				// onにすると新しいコンテンツを読み込むたびにCB_ExternalFunctionLoad()という名前の関数を呼び出す。(useful for audit, etc)
	CB_AllowExtFunctPageLoad='off',				// onにするとページがすべて読み込まれた後に CB_ExternalFunctionPageLoad() という名前の関数を呼び出す。
	CB_AllowExtFunctCBClose='off	'				// onにするとclearboxが終了するときに CB_ExternalFunctionCBClose() という名前の関数を呼び出す。

;

cb_language.js

//                  
// 	ClearBox Language File (JavaScript)
//

var

	CB_NavTextPrv='前',				// text of previous image
	CB_NavTextNxt='次',					// text of next image
	CB_NavTextFull='フルサイズ',				// text of original size (only at pictures)
	CB_NavTextOpen='新しいウィンドウで開く',		// text of open in a new browser window
	CB_NavTextDL='ダウンロード',				// text of download picture or any other content
	CB_NavTextClose='clearboxを閉じる',			// text of close CB
	CB_NavTextStart='スライドショー',			// text of start slideshow
	CB_NavTextStop='停止',			// text of stop slideshow
	CB_NavTextRotR='90度右に回転',	// text of rotation right
	CB_NavTextRotL='90度左に回転',	// text of rotation left
	CB_NavTextReady='clearbox 準備完了'			// text of clearbox ready

;

くどいようですが、適当に直訳してるだけなので原文も一緒に読んでね。

lightboxの類いろいろ試したけどこれが一番簡単だった。

AutoCAD LT でビューポートの視点を90度回転する

2007年1月のメモから引っ張り出してきた。以下、コピペ。

タイトルでロストテクノロジーとかご大層なキーワード出してますが、ようは自分が以前に作ったAutocad LT 用の DIESEL 式を発掘しただけです、はい。

^C^C_tilemode;0;_mspace;_ucs;_z;270;_plan;c;ucs;w;zoom e;

これね。
これは何をするものかというと、モデル画面では縦長の図面を横長のビューポートに収めるために、ビューポートの視点を90度回転させる、それだけのものです。
でまあ非常に単純かつささいな上普段はあまり使わない機能なんですが、あると便利なので 2002 の自作メニューに登録しておいたらしいです。過去の自分は。
しかし、会社で使うマシンが新しくなったときに AutoCAD LT も 2005 になり、自作メニューの一部で(バージョンが違うとコマンド名も変わるために)不具合が出て、面倒くさいので 2002 時代の自作メニューを捨ててしまっておりました。
ですが、先月急に視点を変更させたい図面がいくつか発生し、(昔自分がメニューに登録したことを忘れ)手作業でやろうと思ったらやり方もすっかり忘れていて、結局、すでに視点が回転されている図面を呼び出して、ペーパー画面にあるビューポートと図面枠だけ流用して何とか作成したわけであります。
で、今頃になって、その時あれほど欲しかった機能を実現する DIESEL 式が 2002 時代の自作メニューに登録されていることを発見したので、せっかくだから、またロストする前に日記にメモっておくしだい。

2007年当時に件のエントリーを書きつつ、自分用カスタムメニューにマクロ登録して幾星霜。

新しいPC買ってもらった私はうかれすぎて、大事なマクロを登録したカスタムメニューのバックアップをせずに〜と4年前と同じことを繰り返したわけであります。

……三つ子の魂何とやら。

20110808追記:DIESEL式なんのこっちゃって方のために一応解説追加しときます。

  1. tilemode 0 でレイアウト(ペーパー)画面を選択。
  2. mspace でレイアウト画面にあるビューポートの内部モデル空間に移動。
  3. ucs z 270 でユーザー座標系の設定。Z軸の回転角度を270度に。
  4. plan c でプランビューを現在のユーザー座標系にあわせる。←ここで実際にビューポート内が回転
  5. ucs w でユーザー座標系をワールド座標に戻す
  6. zoom e でオブジェクト範囲にズーム(ビューポート内にすべてのオブジェクトが評されるように)する

ucs z 270;plan c がメインで残りはおまけみたいな。最後のzoomの後にさらにお好きな倍率でzoomコマンド付け加えるのもよいかと。
で、元の表示に戻す時は、ビューポート内で plan w ってやれば、ワールド座標系にあわせたビューに戻ります。

データスキームを使って画像ファイルを埋め込んだimgタグを作成する

(20110808追記:も少しまともに作り直してみた。)
せっかく途中まで作ったけど、今回は使わなさそうなのでいつか使う時のためにメモとして残しておく。
再利用の際は、キャッシュと元ファイルの日付調べてキャッシュが古かったら再生成するっての付け加えるのと、imgタグのaltとサイズちゃんと反映するようにするのと、せっかく投げてる例外をきちんと処理するのと忘れないよう>未来の自分。

<?php 
// 例外を使う
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}
set_error_handler("exception_error_handler");

if(!defined('THUMB_CACHE_EXT')) define('THUMB_CACHE_EXT','.b64'); // キャッシュにくっつける拡張子
if(!defined('THUMB_DIR')) define('THUMB_DIR',''); // サムネールがあるディレクトリ
if(!defined('THUMB_CACHE_DIR')) define('THUMB_CACHE_DIR',''); // キャッシュを保存するディレクトリ

// base64でエンコードした画像データをIMGタグの中に埋め込んで返す
// 参考 : http://en.wikipedia.org/wiki/Data_URI_scheme
function get_thumb_itag($tfile,$alt='',$x=0,$y=0,$odir='',$cdir=''){
	if(!$odir) $odir = THUMB_DIR;
	if(!$cdir) $cdir = THUMB_CACHE_DIR;
	$ofile = $odir.$tfile;
	$cfile = $cdir.$tfile.THUMB_CACHE_EXT;
	try{
		if(file_exists($cfile)){
			$txt = file_get_contents($cfile);
		}
		else{
			$bin = file_get_contents($ofile);
			$txt = base64_encode($bin);
			fwrite(fopen($cfile, "w"), $txt, strlen($txt)); // cache保存
		}
	}
	catch (Exception $e) {
		var_dump($e->getMessage());
	}
	if($txt){
		$itag = '<img src="data:image/jpeg;base64,'.$txt.'" alt="sample"/>';
	}
	else{
		$itag = 'えらーだって';
	}
	return $itag;
}

// 指定のキャッシュ削除
function delete_thumb_cache($tfile,$cdir=''){
	if(!$cdir) $cdir = THUMB_CACHE_DIR;
	$cfile = $cdir.$tfile.THUMB_CACHE_EXT;
	try{
		unlink($cfile);
	}
	catch (Exception $e) {
		var_dump($e->getMessage());
	}
	return 1;
}

?>
<?php echo get_thumb_itag('sample.jpg');?>

VertrigoServ上でPEARを使う

20110808追記:

VartrigoServに含まれてるphpも公式配布のWindows版と同じく go-pear に不具合があるようなので、そのままだとインストール時にエラーが起きて何度やってもうまく動かない。(てか、こっちの方が大きい問題な気がする……)
このあたりを参考に修正するか、http://pear.php.net/go-pearから不具合のないgo-pear.pharをダウンロードして上書きするか。
私はgo-pear.pharを上書きして、php go-pear.phar を実行し、インストール作業を進めることに成功した。
以下は、go-pear.pharを上書きした後もなおインストール先及びphp.iniの保存先で引っかかった件についてのメモ。(追記ここまで)

はまったのでメモ。

go-pear.pharを実行する前に以下の環境変数設定しときましょうねと。

[HKEY_CURRENT_USER\Environment]
"PHP_DIR"="C:\\VertrigoServ\\Php"
"PHP_PEAR_BIN_DIR"="%PHP_DIR%"
"PHP_PEAR_CACHE_DIR"="%PHP_DIR%\\PEAR\\cache"
"PHP_PEAR_CFG_DIR"="%PHP_DIR%\\PEAR\\cfg"
"PHP_PEAR_DATA_DIR"="%PHP_DIR%\\PEAR\\data"
"PHP_PEAR_DOC_DIR"="%PHP_DIR%\\PEAR\\docs"
"PHP_PEAR_EXTENSION_DIR"="%PHP_DIR%\\PEAR"
"PHP_PEAR_INSTALL_DIR"="%PHP_DIR%\\PEAR\\pear"
"PHP_PEAR_PHP_BIN"="%PHP_DIR%\\php.exe"
"PHP_PEAR_SYSCONF_DIR"="%PHP_DIR%\\PEAR"
"PHP_PEAR_TEST_DIR"="%PHP_DIR%\\PEAR\\tests"
"PHP_PEAR_WWW_DIR"="%PHP_DIR%\\PEAR\\www"

XPなどで使う分にはデフォルトのままでも問題ないのだけど、Windows 7はシステムが管理するフォルダにあるファイルをユーザー権限で変更するのがひっじょーに面倒くさい。
VertrigoServをProgram Files以下に保存すると、http.confやphp.iniなどの設定ファイル書き換えるたびにイライラする羽目になる。
そこで私はVertrigoServのインストール先をC:\VertrigoServにしてある。
PEARをインストールすると一部の環境変数を登録できるようなレジストリファイルを作ってくれるのでそれ登録してもいいような気もする。
でも先に指定しておかないとwwwとかのフォルダがPEARの外に作られてしまうのでやっぱり先に環境変数設定しておいたほうがいいかもしれない。
別のPCにインストールするときに再度確認してみよう。

大きなお世話的ブラウザやその他のソフトでスペルチェックを止める設定

邪魔だと思うんだけどなー。IE以外の主要ブラウザ全部ついてるんだよなー。

Opera 12 以前 (いわゆる Presto版)

設定>詳細>閲覧ダイアログの「スペルチェック」をオフにする。

Firefox

オプション>詳細>一般>「自動スペルチェック機能を使用する」をオフにする。

Chrome

オプション>高度な設定>ウェブコンテンツの「言語とスペルチェックの設定」ボタンを押し、

下のほうにある「スペルチェックを有効にする」をオフにする。

ついでに、高度な設定>翻訳>「母国語以外のページで翻訳ツールを表示する」もオフにするとさらに幸せになれるね。
(20120404 こっから追記)

Thunderbird

オプション>編集>スペルチェックタブの「自動スペルチェック機能を使用する」をオフにする。

Microsoft Office

参考画像はExcel2010のだけど、Officeはみんなダイアログを出す手順ほぼ一緒。Wordだとも少し設定項目増えます。
Officeの場合はスペルチェックよりオートコレクトのほうが実害多いので、そちらも止めるのは必須だと思われ。

2003まで
ツール>オプション>文書校正
2007以降
ファイル(左上色のついたタブ)>オプション>文書校正(Outlookはオプション>メール>スペルチェックとオートコレクト>文書校正)

思いついたら増やすかも。