2015年8月26日 星期三

使用 PHP 內建的 HTTP server

參考連結
https://docs.phalconphp.com/en/latest/reference/built-in.html
https://gist.github.com/tamagokun/3801087
http://www.sitepoint.com/taking-advantage-of-phps-built-in-server/

在 PHP 5.4.0 之後,就內建 HTTP server,可以很方便的測試網頁。甚至代替網芳,用來傳檔案也很方便。

只要下這樣的指令,就可以了。
php -S localhost:8000 -t /web_root

只是不支援 Apache 的 .htaccess 和 mod_rewrite,對於省略 index.php 的網址,必須用其他方式達成。

交易時,我會找很多理由,不守紀律

交易時 我會找很多理由 不守紀律

2015年8月4日 星期二

在 Wine 下安裝 Sublime Text 3

(Install Sublime text 3 under Wine)

雖然,有 Linux 版的 Sublime Text 3,中文輸入也已設定成功,但是,text drag and drop 的功能在 Linux 下是無效的,我的決擇是捨中文輸入,選擇文字拖曳的功能。因此,又在想著如何透過 Wine 來執行 Sublime Text 3。

照著先前的作法,裝了 vcrun2010,仍然是意外死亡。最後,抱著試一試的想法,使用 winetricks,將上面可以裝的東西,都裝裝看,看是否運氣好,能夠讓 Sublime Text 3 跑起來。運氣還不錯,終於成功執行。總計裝了 dotnet20, dotnet20sp1, dotnet30sp1, glut,vcrun2010 倒沒有裝。不曉得是那個有用。將目錄整個砍掉,重來一次就知道了。

== Related Information ==

OS: Gentoo Linux, kernel: 3.18.12
Wine: 1.7.47, Winetricks: 20150706
Sublime Text 3 - build 3083
Required package:  dotnet20sp1 or dotnet20sp2
Native DLL:  dwrite.dll

一樣,為個別的軟體建個專用目錄,建立虛擬目錄。
$ WINEARCH=win32 WINEPREFIX=~/wine-sublime3 winecfg
選擇Windows 版本: Windows 7

設定虛擬目錄的環境變數
$ export WINEPREFIX=~/wine-sublime3

安裝 Sublime Text

可以執行
$ wine explorer
點選安裝檔,進行安裝。或是把安裝檔 copy 至 ~\wine-sublime3\drive_c\ 下,然後執行
$ wine c:\\Sublime\ Text\ Build\ 3083\ Setup.exe

$ wine Z:\\home\\ajax\\Downloads\\Sublime\\Sublime\ Text\ Build\ 3126\ Setup.exe

執行看看,
$ wine "C:\\Program Files\\Sublime Text 3\\subl.exe"
嗯,出現嚴重錯誤!

先裝 .NET 2.0 Framework SP1 或 SP2
$ winetricks dotnet20sp1

再試一次,可以成功執行,但畫面是亂的,這已有經驗了。透過 winecfg 的函式庫功能,將 dwrite.dll 設成原生 (native) 即可。dwrite.dll 是一個系統的 DLL 檔,該檔的描述為 Microsoft DirectX Typography Services。
大功告成,可以舒服的用了。
另外,package control 也不能用,那就用手動安裝吧,反正也做慣黑手了。

InputHelper

Linux 版本的 Sublime Text 會有中文輸入的問題,在 Wine 下執行,也同樣無法直接輸入中文,只好暫時用 copy and paste 的方式。很幸運的,經過一些嘗試,可以用 InputHelpler 輸入中文了。依網路上找到的資料,下載 InputHelper,然後複製到 ~/wine-sublime3/drive_c/users/ajax/Application Data/Sublime Text 3/Packages/ 的目錄下,再修改下列的部分
1. Default (Linux).sublime-keymap 改名為 Default (Windows).sublime-keymap 
2. 修改 inputhelper.py 的下面兩個地方
    (1) if sublime.platform() == 'windows': 
    (2) args = ["cmd", "/c", location]
3. 修改 linux_text_input_gui.py 的第一行為 #!/usr/bin/env python2,因為 pygtk 目前只有 Python 2 的版本,而我的 OS 預設是 Python 3

注意,依照上述方式執行,Sublime 是在 WINE 的環境中執行,但 InputHelper 則是在 Linux 的環境中執行。

衍生問題,ctrl_space 在 sublime 中,已有定義。編輯時不小心按到,會切換中英文輸入模式,但無法輸入中文,更進一步,有一些快速鍵也會失效。因此,在執行 Sublime 之前,必須 unset XMODIFIERS 環境變數,使中文輸入在 Sublime 中不會有作用。

#!/bin/bash
unset XMODIFIERS
export WINEPREFIX="/home/ajax/wine-sublime3"
wine "C:\\Program Files\\Sublime Text 3\\subl.exe"


設定 sidebar 的字型大小

透過 [Browse Packages] 功能,找出其下的 [User] 目錄,建立 Default.sublime-theme,加上下面的內容

[
  {
    "class": "sidebar_label",
    "color": [0, 0, 0],
    "font.bold": false,
    "font.size": 12
  }
]


假如是使用別的 theme,則依其名稱而不同,例如 Material-Theme-Darker.sublime-theme

補記

目前,我的筆電還是裝 Wine 的穩定版是 Wine 1.6.2,照著上面的步驟再裝一次,但安裝 Sublime Text 3後,無法成功執行。記得在先前的試裝過程中,看到 mono 的訊息,Wine 1.6.2 中,裝的是 wine-mono-0.0.8.msi,而 Wine 1.7.47 裝的是 wine-mono-4.5.6.msi,差別可能在此吧。升級至 Wine 1.7.47 ,就可以成功執行,舊版的 Wine 也就不再多試了。

2017-06-01 記

升級到 app-emulation/wine-any-2.7,仍是 mask,會自動裝 app-emulation/wine-desktop-common、app-emulation/wine-gecko、app-emulation/wine-mono-4.7.0,幾乎不用再做任何設定,直接裝 sublime-text 即可使用。

2017-09-15 記

在前一版推出的一年之後,2017年9月13日,Build 3143 發行。馬上安裝試用,結果字型變得很難看,也無法使用先前的 Color Scheme,只好再回去用 Build 3126。為了一直避免跳出 update 的提示視窗,在 setting 裡加上下面的設定
  "update_check": false,


2018-10-09 記

不知是那裡改變了,變成 InputHelper 可以輸入中文,但無法貼到編輯的文件中。然後,設定 XMODIFIERS=@im=gcin 就可以輸入中文了。

WINE 的功能表

用 WINE 執行安裝之後,會在功能表上出現選項,例如  Wine >  Programs > Sublime Text 3 對應的檔案在
~/.local/share/applications/wine/Programs/Sublime Text 3.desktop

2015年8月3日 星期一

VM 中使用智慧卡讀卡機

在 VMware 的 VM 中,可以用分享的方式使用智慧卡讀卡機 (smart card reader)。

在 Linux host 中,安裝 pcsc-lite 及 ccid driver。再啟動 pcscd 的 daemon。
Vmare 的 config 中,要加上 usb.ccid.useSharedMode = "TRUE" 的設定

參考
https://pubs.vmware.com/workstation-9/index.jsp?topic=%2Fcom.vmware.ws.using.doc%2FGUID-8AA77FED-BE63-45CB-8FB6-6D7C4A35F76B.html

假如不要使用分享的方式使用智慧卡讀卡機
則修改 VM 的設定檔,例如 Win_XP.vmx ,加入
usb.generic.allowCCID = "TRUE"
usb.ccid.disable = "TRUE"



VMware Workstation Pro 16.0

參考 Disable Smart Card Sharing

修改 /etc/vmware/config,加上
usb.ccid.useSharedMode = "FALSE"

不過還是看不到,就算把 "Show all USB input devices" 打勾也是看不到。











2015年8月1日 星期六

在 Linux 版的 Sublime Text 3 中,使用 gcin 輸入中文

 今天試用了 Sublime Text 3, 要支援中文輸入,得用 fcitx 輸入法,但是實在不習慣它的拆字界面,還是覺得使用 gcin 比較順手。但知道憑一己之力,不知那時才有成功的可能。很幸運的是,爬文幾個小時候,發現在網友的互相討論之下,已有了解決方式。
參考連結如下。

http://www.sublimetext.com/forum/viewtopic.php?f=3&t=7006&start=10#p41343
http://www.sublimetext.com/forum/viewtopic.php?f=3&t=7006&start=20#p61143
(以上為 Sublime Text forum)
http://whitequark.org/blog/2014/04/14/xcompose-support-in-sublime-text/

PS: 我使用的是 Gentoo Linux

原始碼
    /*
    sublime-imfix.c
    Use LD_PRELOAD to interpose some function to fix sublime input method support for linux.
    By Cjacker Huang <jianzhong.huang at i-soft.com.cn>
    By whitequark@whitequark.org

    How to compile:
    gcc -shared -o libsublime-imfix.so sublime_imfix.c  `pkg-config --libs --cflags gtk+-2.0` -fPIC
    How to use:
    LD_PRELOAD=./libsublime-imfix.so sublime_text

    Changes:
    2014 06-09
    1, Fix cursor position update for sublime text 3.
    2, Combine the codes from whitequark(fix for xim immodule) and add cursor update support for XIM immodule.
    */

    /*for RTLD_NEXT*/
    #define _GNU_SOURCE

    #include <gtk/gtk.h>
    #include <gdk/gdkx.h>
    #include <assert.h>
    #include <dlfcn.h>
    #include <stdio.h>
    #include <string.h>
    #include <gtk/gtk.h>
    #include <X11/Xlib.h>
    #include <X11/Xutil.h>

    #ifdef VERBOSE
    #define DEBUG(fmt, ...) do { \
        FILE* err = fopen("/tmp/libsublime-immethod-fix.log", "a"); \
        if (err) { \
          fprintf(err, fmt, __VA_ARGS__); \
          fclose(err); \
        } \
      } while(0)
    #else
    #define DEBUG(fmt, ...)
    #endif

    typedef GdkSegment GdkRegionBox;

    struct _GdkRegion
    {
      long size;
      long numRects;
      GdkRegionBox *rects;
      GdkRegionBox extents;
    };

    GtkIMContext *local_context;

    //this func is interposed to support cursor position update.
    void gdk_region_get_clipbox (const GdkRegion *region,
                GdkRectangle    *rectangle)
    {
      g_return_if_fail (region != NULL);
      g_return_if_fail (rectangle != NULL);

      rectangle->x = region->extents.x1;
      rectangle->y = region->extents.y1;
      rectangle->width = region->extents.x2 - region->extents.x1;
      rectangle->height = region->extents.y2 - region->extents.y1;
      GdkRectangle rect;
      rect.x = rectangle->x;
      rect.y = rectangle->y;
      rect.width = 0;
      rect.height = rectangle->height;
      //The caret width is 2 in sublime text 2
      //And is 1 in sublime text 3.
      //Maybe sometimes we will make a mistake, but for most of the time, it should be the caret.
      if((rectangle->width == 2 || rectangle->width == 1)  && GTK_IS_IM_CONTEXT(local_context)) {
            gtk_im_context_set_cursor_location(local_context, rectangle);
      }
    }

    //this is needed, for example, if you input something in file dialog and return back the edit area
    //context will lost, so here we set it again.
    static GdkFilterReturn event_filter (GdkXEvent *xevent, GdkEvent *event, gpointer im_context)
    {
        XEvent *xev = (XEvent *)xevent;
        if(xev->type == KeyRelease && GTK_IS_IM_CONTEXT(im_context)) {
           GdkWindow * win = g_object_get_data(G_OBJECT(im_context),"window");
           if(GDK_IS_WINDOW(win))
             gtk_im_context_set_client_window(im_context, win);
        }
        return GDK_FILTER_CONTINUE;
    }

    void gtk_im_context_set_client_window (GtkIMContext *context,
              GdkWindow    *window)
    {
        GtkIMContextClass *klass;
        g_return_if_fail (GTK_IS_IM_CONTEXT (context));
        klass = GTK_IM_CONTEXT_GET_CLASS (context);
        if (klass->set_client_window)
            klass->set_client_window (context, window);

        //below is our interposed codes to save the context to local_context.
        if(!GDK_IS_WINDOW (window))
            return;
        g_object_set_data(G_OBJECT(context),"window",window);
        int width = gdk_window_get_width(window);
        int height = gdk_window_get_height(window);
        if(width != 0 && height !=0) {
            gtk_im_context_focus_in(context);
            local_context = context;
        }
        //only add this event_filter when using 'fcitx' immodule.
        //for xim immodule, this function is as same as original from gtk2.
        const gchar * immodule = g_getenv("GTK_IM_MODULE");
        if(immodule && !strcmp(immodule, "fcitx")) {
            gdk_window_add_filter (window, event_filter, context);
        }
    }

    /*below codes is from whitequark, fix for xim immodule */

    /* See gtkimcontextxim.c */
    GType gtk_type_im_context_xim = 0;

    #define GTK_TYPE_IM_CONTEXT_XIM            (gtk_type_im_context_xim)
    #define GTK_IM_CONTEXT_XIM(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIM))
    #define GTK_IM_CONTEXT_XIM_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIMClass))
    #define GTK_IS_IM_CONTEXT_XIM(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_IM_CONTEXT_XIM))
    #define GTK_IS_IM_CONTEXT_XIM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_XIM))
    #define GTK_IM_CONTEXT_XIM_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_XIM, GtkIMContextXIMClass))

    typedef struct _GtkIMContextXIM       GtkIMContextXIM;
    typedef struct _GtkIMContextXIMClass  GtkIMContextXIMClass;

    struct _GtkIMContextXIMClass
    {
      GtkIMContextClass parent_class;
    };

    typedef struct _StatusWindow StatusWindow;
    typedef struct _GtkXIMInfo GtkXIMInfo;

    struct _GtkIMContextXIM
    {
      GtkIMContext object;

      GtkXIMInfo *im_info;

      gchar *locale;
      gchar *mb_charset;

      GdkWindow *client_window;
      GtkWidget *client_widget;

   /* The status window for this input context; we claim the
    * status window when we are focused and have created an XIC
    */
      StatusWindow *status_window;

      gint preedit_size;
      gint preedit_length;
      gunichar *preedit_chars;
      XIMFeedback *feedbacks;

      gint preedit_cursor;

      XIMCallback preedit_start_callback;
      XIMCallback preedit_done_callback;
      XIMCallback preedit_draw_callback;
      XIMCallback preedit_caret_callback;

      XIMCallback status_start_callback;
      XIMCallback status_done_callback;
      XIMCallback status_draw_callback;

      XIMCallback string_conversion_callback;

      XIC ic;

      guint filter_key_release : 1;
      guint use_preedit : 1;
      guint finalizing : 1;
      guint in_toplevel : 1;
      guint has_focus : 1;
    };

    static GClassInitFunc orig_gtk_im_context_xim_class_init;
    static GType (*orig_g_type_module_register_type)(
            GTypeModule *, GType, const gchar *, const GTypeInfo *,
            GTypeFlags);
    static gboolean (*orig_gtk_im_context_xim_filter_keypress)(
            GtkIMContext *context, GdkEventKey *event);

    static gboolean
    hook_gtk_im_context_xim_filter_keypress(GtkIMContext *context, GdkEventKey *event)
    {
      GtkIMContextXIM *im_context_xim = GTK_IM_CONTEXT_XIM(context);
      if (!im_context_xim->client_window) {
        DEBUG("im_context_xim == %p\n", im_context_xim);
        DEBUG("event->window == %p\n", event->window);

        gtk_im_context_set_client_window(context, event->window);
      }

      return orig_gtk_im_context_xim_filter_keypress(context, event);
    }

    static void hook_gtk_im_context_xim_class_init (
            GtkIMContextXIMClass *class)
    {
      orig_gtk_im_context_xim_class_init(class, NULL); /* wat? */

      GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);

      assert(!orig_gtk_im_context_xim_filter_keypress);
      orig_gtk_im_context_xim_filter_keypress = im_context_class->filter_keypress;
      im_context_class->filter_keypress = hook_gtk_im_context_xim_filter_keypress;
      DEBUG("orig_gtk_im_context_xim_filter_keypress: %p\n",
            orig_gtk_im_context_xim_filter_keypress);
    }

    GType
    g_type_module_register_type (GTypeModule *module,
                                 GType parent_type,
                                 const gchar *type_name,
                                 const GTypeInfo *type_info,
                                 GTypeFlags flags)
    {
      if (!orig_g_type_module_register_type) {
        orig_g_type_module_register_type = dlsym(RTLD_NEXT, "g_type_module_register_type");
        assert(orig_g_type_module_register_type);
      }

      if (type_name && !strcmp(type_name, "GtkIMContextXIM")) {
        assert(!orig_gtk_im_context_xim_class_init);
        orig_gtk_im_context_xim_class_init = type_info->class_init;

        assert(sizeof(GtkIMContextXIM) == type_info->instance_size);

        const GTypeInfo hook_im_context_xim_info =
        {
          type_info->class_size,
          type_info->base_init,
          type_info->base_finalize,
          (GClassInitFunc) hook_gtk_im_context_xim_class_init,
          type_info->class_finalize,
          type_info->class_data,
          type_info->instance_size,
          type_info->n_preallocs,
          type_info->instance_init,
        };

        DEBUG("orig_gtk_im_context_xim_class_init: %p\n", orig_gtk_im_context_xim_class_init);

        gtk_type_im_context_xim =
          orig_g_type_module_register_type(module, parent_type,
              type_name, &hook_im_context_xim_info, flags);

        return gtk_type_im_context_xim;
      }

      return orig_g_type_module_register_type(module, parent_type, type_name, type_info, flags);
    }



編譯:
$ gcc -shared -o libsublime-imfix.so sublime-imfix.c  `pkg-config --libs --cflags gtk+-2.0` -fPIC

設定環境變數:
$ export GTK_IM_MODULE=xim

執行:
$ LD_PRELOAD=./libsublime-imfix.so subl3

如上,Sublime Text 3 中文切換,必需將 GTK_IM_MODULE 設成 xim
但是會讓所有的程式,gcin 的輸入視窗都黏在視窗左上角,不會跟著程式的游標 。
只好要用 Sublime Text 時,才設成 xim。終究能夠直接輸入中文,比起以往必需用 copy and paste 來輸入中文,要好得多了。

另外,有下面一些小小的不便。
  • 在輸入中文時,若想用 Backspace 來修正時,無法刪除輸入的字根,反而會刪除編輯的內容。必須按 Escape 鍵,取消所有的輸入,重新輸一次。
  • 無法用 ctrl+, 或 ctrl+. 來輸入中文的豆號和句號。
修改 sublime-text-3.desktop 中的執行指令
Exec=bash -c 'GTK_IM_MODULE=xim LD_PRELOAD=/usr/local/lib/libsublime-imfix.so subl3' %F



關於中文輸入法的環境變數的設定,可以參考
http://moto.debian.tw/viewtopic.php?t=9525

如果是 GTK(gnome) 的程式,可能你沒有設定 GTK_IM_MODULE=gcin, QT 的程式必須在在 qtconfig 設定 XIM over-the-spot。如果你的 QT 支援 QT_IM_MODULE,只要設定 QT_IM_MODULE=gcin就可以了。

網誌存檔