⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 odbc3.c

📁 一个可以替代windows ODBC驱动程序管理器的通用ODBC数据库引擎
💻 C
📖 第 1 页 / 共 3 页
字号:
	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ROWS_FETCHED_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if (ValuePtr)	    *((SQLPOINTER *) ValuePtr) = stmt->rows_fetched_ptr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_METADATA_ID:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if (ValuePtr)	    *((SQLUINTEGER *) ValuePtr) = SQL_FALSE;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_PARAMS_PROCESSED_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if (ValuePtr)	    *((SQLUINTEGER **) ValuePtr) = stmt->params_processed_ptr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_PARAMSET_SIZE:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if (ValuePtr)	    *((SQLUINTEGER *) ValuePtr) = stmt->paramset_size;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ROW_STATUS_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if (ValuePtr)	    *((SQLUINTEGER **) ValuePtr) = stmt->row_status_allocated == SQL_FALSE ?		stmt->row_status_ptr :		NULL;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ASYNC_ENABLE:    case SQL_ATTR_MAX_ROWS:    case SQL_ATTR_QUERY_TIMEOUT:    case SQL_ATTR_CONCURRENCY:    case SQL_ROWSET_SIZE:    case SQL_ATTR_CURSOR_TYPE:    case SQL_ATTR_KEYSET_SIZE:    case SQL_ATTR_NOSCAN:    case SQL_ATTR_RETRIEVE_DATA:    case SQL_ATTR_ROW_BIND_TYPE:    case SQL_ATTR_ROW_NUMBER:    case SQL_ATTR_SIMULATE_CURSOR:    case SQL_ATTR_USE_BOOKMARKS:    case SQL_ATTR_MAX_LENGTH:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtOption);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtOption,		  (stmt->dhstmt, Attribute, ValuePtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}    default:      hproc = _iodbcdm_getproc (stmt->hdbc, en_GetStmtAttr);      if (hproc)	{	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_GetStmtAttr,	      (stmt->dhstmt, Attribute, ValuePtr, BufferLength, StringLengthPtr));	  LEAVE_STMT (stmt, retcode);	}      else	{	  PUSHSQLERR (stmt->herr, en_IM001);	  LEAVE_STMT (stmt, SQL_ERROR);	}    }  LEAVE_STMT (stmt, SQL_SUCCESS);}/**** SQLSetStmtAttr ****/RETCODE SQL_APISQLSetStmtAttr (SQLHSTMT statementHandle,    SQLINTEGER Attribute,    SQLPOINTER ValuePtr,    SQLINTEGER StringLength){  STMT (stmt, statementHandle);  HPROC hproc;  RETCODE retcode;  ENTER_STMT (stmt);  if (stmt->state == en_stmt_needdata)    {      PUSHSQLERR (stmt->herr, en_HY010);      LEAVE_STMT (stmt, SQL_ERROR);    }  switch (Attribute)    {    case SQL_ATTR_APP_PARAM_DESC:      if (ValuePtr == SQL_NULL_HDESC || ValuePtr == stmt->imp_desc[APP_PARAM_DESC])	{	  HDESC hdesc = ValuePtr == SQL_NULL_HDESC ? ValuePtr : stmt->imp_desc[APP_PARAM_DESC]->dhdesc;	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (!hproc)	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,	      (stmt->dhstmt, Attribute, hdesc, StringLength));	  if (retcode != SQL_SUCCESS || retcode != SQL_SUCCESS_WITH_INFO)	    LEAVE_STMT (stmt, SQL_ERROR);	  stmt->desc[APP_PARAM_DESC] = SQL_NULL_HDESC;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}      if (!IS_VALID_HDESC (ValuePtr))	{	  PUSHSQLERR (stmt->herr, en_HY024);	  LEAVE_STMT (stmt, SQL_ERROR);	}      else	{	  DESC (pdesc, ValuePtr);	  if (pdesc->hdbc != stmt->hdbc || IS_VALID_HSTMT (pdesc->hstmt))	    {	      PUSHSQLERR (stmt->herr, en_HY017);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (!hproc)	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,	      (stmt->dhstmt, Attribute, pdesc->dhdesc, StringLength));	  if (retcode != SQL_SUCCESS || retcode != SQL_SUCCESS_WITH_INFO)	    LEAVE_STMT (stmt, SQL_ERROR);	  stmt->desc[APP_PARAM_DESC] = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_APP_ROW_DESC:      if (ValuePtr == SQL_NULL_HDESC || ValuePtr == stmt->imp_desc[APP_ROW_DESC])	{	  HDESC hdesc = ValuePtr == SQL_NULL_HDESC ? ValuePtr : stmt->imp_desc[APP_ROW_DESC]->dhdesc;	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (!hproc)	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,	      (stmt->dhstmt, Attribute, hdesc, StringLength));	  if (retcode != SQL_SUCCESS || retcode != SQL_SUCCESS_WITH_INFO)	    LEAVE_STMT (stmt, SQL_ERROR);	  stmt->desc[APP_ROW_DESC] = SQL_NULL_HDESC;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}      if (!IS_VALID_HDESC (ValuePtr))	{	  PUSHSQLERR (stmt->herr, en_HY024);	  LEAVE_STMT (stmt, SQL_ERROR);	}      else	{	  DESC (pdesc, ValuePtr);	  if (pdesc->hdbc != stmt->hdbc || IS_VALID_HSTMT (pdesc->hstmt))	    {	      PUSHSQLERR (stmt->herr, en_HY017);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (!hproc)	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,	      (stmt->dhstmt, Attribute, pdesc->dhdesc, StringLength));	  if (retcode != SQL_SUCCESS || retcode != SQL_SUCCESS_WITH_INFO)	    LEAVE_STMT (stmt, SQL_ERROR);	  stmt->desc[APP_ROW_DESC] = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_CURSOR_SCROLLABLE:    case SQL_ATTR_CURSOR_SENSITIVITY:    case SQL_ATTR_ENABLE_AUTO_IPD:    case SQL_ATTR_METADATA_ID:    case SQL_ATTR_PARAM_BIND_OFFSET_PTR:    case SQL_ATTR_PARAM_BIND_TYPE:    case SQL_ATTR_PARAM_OPERATION_PTR:    case SQL_ATTR_PARAM_STATUS_PTR:    case SQL_ATTR_ROW_BIND_OFFSET_PTR:    case SQL_ATTR_ROW_OPERATION_PTR:      hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);      if (!hproc)	{	  PUSHSQLERR (stmt->herr, en_IM001);	  LEAVE_STMT (stmt, SQL_ERROR);	}      else	{	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,	      (stmt->dhstmt, Attribute, ValuePtr, StringLength));	  LEAVE_STMT (stmt, retcode);	}    case SQL_ATTR_ROWS_FETCHED_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  stmt->rows_fetched_ptr = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_FETCH_BOOKMARK_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  stmt->fetch_bookmark_ptr = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_PARAMS_PROCESSED_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  stmt->params_processed_ptr = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_PARAMSET_SIZE:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  stmt->paramset_size = (SQLUINTEGER) ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ROW_ARRAY_SIZE:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  if ((SQLUINTEGER) ValuePtr < 1)	    {	      PUSHSQLERR (stmt->herr, en_HY024);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  stmt->row_array_size = (SQLUINTEGER) ValuePtr;	  /* reallocate the row_status_ptr */	  if (stmt->row_status_ptr && stmt->row_status_allocated == SQL_TRUE)	    {	      MEM_FREE (stmt->row_status_ptr);	      stmt->row_status_allocated = SQL_FALSE;	    }	  stmt->row_status_ptr = MEM_ALLOC (sizeof (SQLUINTEGER) * stmt->row_array_size);	  if (!stmt->row_status_ptr)	    {	      PUSHSQLERR (stmt->herr, en_HY001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  stmt->row_status_allocated = SQL_TRUE;	  /*	   *  Tell the driver the rowset size has changed	   */	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtOption);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtOption,		  (stmt->dhstmt, SQL_ROWSET_SIZE, stmt->row_array_size));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ROW_STATUS_PTR:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  /* free the implicit row status ptr (if any) */	  if (stmt->row_status_ptr && stmt->row_status_allocated == SQL_TRUE)	    {	      MEM_FREE (stmt->row_status_ptr);	      stmt->row_status_allocated = SQL_FALSE;	    }	  stmt->row_status_ptr = ValuePtr;	  LEAVE_STMT (stmt, SQL_SUCCESS);	}    case SQL_ATTR_ASYNC_ENABLE:    case SQL_ATTR_CONCURRENCY:    case SQL_ATTR_CURSOR_TYPE:    case SQL_ATTR_KEYSET_SIZE:    case SQL_ATTR_MAX_ROWS:    case SQL_ATTR_NOSCAN:    case SQL_ATTR_QUERY_TIMEOUT:    case SQL_ATTR_RETRIEVE_DATA:    case SQL_ATTR_ROW_BIND_TYPE:    case SQL_ATTR_ROW_NUMBER:    case SQL_ATTR_SIMULATE_CURSOR:    case SQL_ATTR_USE_BOOKMARKS:    case SQL_ROWSET_SIZE:    case SQL_ATTR_MAX_LENGTH:      if (((ENV_t FAR *) ((DBC_t FAR *) stmt->hdbc)->henv)->dodbc_ver == SQL_OV_ODBC3)	{	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtAttr);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtAttr,		  (stmt->dhstmt, Attribute, ValuePtr, StringLength));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}      else	{			/* an ODBC2 driver */	  hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtOption);	  if (hproc)	    {	      CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtOption,		  (stmt->dhstmt, Attribute, ValuePtr));	      LEAVE_STMT (stmt, retcode);	    }	  else	    {	      PUSHSQLERR (stmt->herr, en_IM001);	      LEAVE_STMT (stmt, SQL_ERROR);	    }	}    default:      hproc = _iodbcdm_getproc (stmt->hdbc, en_SetStmtOption);      if (hproc)	{	  CALL_DRIVER (stmt->hdbc, stmt, retcode, hproc, en_SetStmtOption,	      (stmt->dhstmt, Attribute, ValuePtr));	  LEAVE_STMT (stmt, retcode);	}      else	{	  PUSHSQLERR (stmt->herr, en_IM001);	  LEAVE_STMT (stmt, SQL_ERROR);	}    }  LEAVE_STMT (stmt, (SQL_SUCCESS));}RETCODE SQL_APISQLSetConnectAttr (SQLHDBC connectionHandle,    SQLINTEGER Attribute,    SQLPOINTER ValuePtr,    SQLINTEGER StringLength){  CONN (con, connectionHandle);  HPROC hproc;  RETCODE retcode;  ENTER_HDBC (con);  if (con->state == en_dbc_needdata)    {      PUSHSQLERR (con->herr, en_HY010);      LEAVE_HDBC (con, SQL_ERROR);    }  hproc = _iodbcdm_getproc (con, en_SetConnectAttr);  if (hproc)    {      CALL_DRIVER (con, con, retcode, hproc, en_SetConnectAttr,	  (con->dhdbc, Attribute, ValuePtr, StringLength));      LEAVE_HDBC (con, retcode);    }  switch (Attribute)    {    case SQL_ATTR_AUTO_IPD:      PUSHSQLERR (con->herr, en_HY092);      LEAVE_HDBC (con, SQL_ERROR);    default:      retcode = 	_iodbcdm_SetConnectOption (con, Attribute, (SQLUINTEGER) ValuePtr);      LEAVE_HDBC (con, retcode);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -