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

📄 webprint.java

📁 一个完整的
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/**
公司:北京方成科技发展有限公司
作者:梅勇
日期:2001.08.24
*/
import java.io.*;
import java.text.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.sql.*;
//import explato.database.*;
import sun.io.ByteToCharConverter; 



import org.xml.sax.* ;
import org.apache.xerces.dom.TextImpl;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import dom.DOMParserWrapper;
import dom.wrappers.DOMParser;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class WebPrint extends HttpServlet {
	private int iPosition=1; //用于fc_select类查询中传位置参数
	//数据源名称,用户名,密码.用于报表查询时连接另外的数据源使用,用于fc_select1,fc_select2
	private String strDataSource=""; 
	private String strUserName="";
	private String strPassword="";
	
	private String strXml="";
	private ResultSet rs = null;
	private ResultSet rs1 = null;
	private ResultSet rs2 = null;
	private Connection con = null;
	//private ConnectionManager cm=null;
	private	Document document=null;
	private	javax.sql.DataSource ds=null;
  public void init() {

    try  {

      /* Create a connection to the WebLogic JNDI Naming Service:
       */
      javax.naming.InitialContext ctx = new InitialContext();

      /*  Create a new DataSource by Locating It in the Naming Service:
          OracleThinPool is the name of the connection pool name configed in the WebLogic server container.
          WebLogic data connection pool configration:
          {
          	URL:                     jdbc:oracle:thin:@pyds:1521:toptais  //"toptais" is database name in our RDBMS. "pyds" is DB server name.
            Driver Classname:        oracle.jdbc.driver.OracleDriver
            Properties (key=value):  user=scott
                                     password=tiger
                                     dll=ocijdbc8
                                     protocol=thin
          }
       */
      ds = (javax.sql.DataSource) 
        ctx.lookup ("sqlpool");

    } catch (Exception E) {
      /* 
         Handle exception here. 
      */
      System.out.println("Init Error: " + E);
    }
  }
	
    public void doPost(HttpServletRequest req,
                      HttpServletResponse res)
        throws IOException, ServletException
    {
		//设置演示版,
    	/*
    	long Time1=1026000000+23328000;
    	long curTime=0;
    	curTime=System.currentTimeMillis();
    	curTime=curTime/1000;
    	
    	//每天的时间为 86400
		if(curTime>Time1){ 
    		System.out.println("演示版已到期,系统将不正常!"); 
    		return ;
		}
		//------------------
	*/
        res.setContentType("text/html;charset=UTF-8");
        PrintWriter out = res.getWriter();
		
		try {
	      		//ServletContext application = getServletContext();
			//ConnectionManager cm= (ConnectionManager)application.getAttribute("fcConPoolManager");
			//cm=(ConnectionManager)application.getAttribute ( "fcConPoolManager" );
			//demo是配置文件中逻辑数据库的名字,同时也是连接池的名字

//	String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; 
//	String sConnStr = "jdbc:odbc:ereport"; 
//	Class.forName(sDBDriver);
//	con = DriverManager.getConnection(sConnStr,"sa",""); 

			//con = cm.getConnection( "demo" );     //或者  con = cm.getConnection( "demo", 30000 );   //30000是不能马上取到连接时的等待时间(以毫秒计)
			con = ds.getConnection();

//-----------------------
/*
			Statement stmt = con.createStatement();
			//rs = stmt.executeQuery("SELECT * FROM test");
			con.setAutoCommit(false);
			stmt.executeUpdate("insert into test values('aaa','adfsdfsd')");
			int tran1=stmt.getUpdateCount();
			if (tran1>0){
				con.commit();
			}else{
				con.rollback();
			}
	//		out.println("tran1="+tran1);
			/*String tt;
			while (rs.next()) {
					tt = rs.getString("fstr1");
					out.print("<LI>" + rs.getString("fstr2") + "</LI>");
					out.print("<pre>" + tt + "</pre>");
			}
			rs.close();*/
//----------------------
		} catch (Exception e){
			//out.println("读表发生错误");
			System.out.println("Service Error: " + e);
		}
		/*
		finally {
			if( con != null ){
				cm.freeConnection( "demo", con );
			}
		}
		*/
//-------------------------------------------------------
//strKey为?后的值
	String strKey=new String(req.getQueryString());
//计算前台SEND来的XML串	存入strXml中	
	BufferedReader in = req.getReader();
	String line = null;
	strXml="";
	while ((line = in.readLine()) != null) {
	      strXml=strXml+line;
	    }        
//parse XML串
    try {
        DOMParserWrapper parser =
        (DOMParserWrapper)Class.forName("dom.wrappers.DOMParser").newInstance();
        document = parser.parseXml(strXml);
	}
	catch (Exception e) {
    }
//--------------------------------------------------------	
	//用一个CASE语句来处理各种方法

	if (strKey.equals("fillcombox")) out.print(fillcombox());
	//用于用SQL语句填充combox
	
	if (strKey.equals("GetReportCell")) out.print(GetReportCell()); //跨表取数
	if (strKey.equals("fc_insert")) out.print(fc_insert());
	if (strKey.equals("fc_insert1")) out.print(fc_insert1()); //新增主子表
	if (strKey.equals("fc_update1")) out.print(fc_update1()); //新增主子表
	if (strKey.equals("fc_select")) out.print(fc_select());
	if (strKey.equals("fc_FieldToTable")) out.print(fc_FieldToTable());
	if (strKey.equals("GetDB")) out.print(GetDB());
	if (strKey.equals("fc_select1")) out.print(fc_select1()); //多个SQL同时查的查询
	if (strKey.equals("fc_select2")) out.print(fc_select2()); //明细和汇总都要的查询
	
	if (strKey.equals("twors")) out.print(twors());//两个结果集的测试
	if (strKey.equals("sqltoxml")) out.print(sqltoxml());//两个结果集的测试
	
	if (strKey.equals("dsnSetSession")) 
	{
		Node root = document.getChildNodes().item(0);
        String strName=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
        String strValue="";
        try {
        	//当此节点值为空时
        	strValue=root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
		}
		catch (Exception e) {   }
	
		HttpSession session = req.getSession(true);
		session.setAttribute(strName, strValue);
		out.print("");
	}
	if (strKey.equals("dsnGetSession")) 
	{
		Node root = document.getChildNodes().item(0);
        String strName=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
		HttpSession session = req.getSession(true);
		String strSR=session.getAttribute(strName).toString();;
		out.print(strSR);
	}
	
			if (strKey.equals("loadprint")) { 
				String strX="function%20detachPage%28%29%7B%20htmlToptmp%3DhtmlTop%3B%20htmlBottomtmp%3DhtmlBottom%3B%20var%20iStart%3D0%3B%20var%20iEnd%3D0%3B%20var%20lngEndLine%3Dt.rows.length-tabCauda%3B%20var%20colwidthXML%3DLoadUserData%28%22setcolwidth%22%2C%22ReportColWidth%22+ReportName%29%3B%20effectiveWidth%3DparseInt%28repWidth-tabLeft-tabRight%29%3B%20var%20oXML1%3Dnew%20ActiveXObject%28%22Microsoft.XMLDOM%22%29%3B%20oXML1.async%3D%22false%22%3B%20oXML1.loadXML%28%22%3Croot%3E%22%20+colwidthXML+%22%3C/root%3E%22%29%3B%20sumcol%3D0%3B%20var%20compressRate%3D1%3B%20if%28prnSet.compressWidth%3D%3D1%29%20%7B%20for%20%28var%20j%3D0%3Bj%3CMaxCols%3Bj++%29%7B%20if%20%28oXML1.documentElement.childNodes.item%28j%29.getAttribute%28%22colSelect%22%29%3D%3D%22block%22%29%7B%20sumcol%3Dsumcol+parseInt%28oXML1.documentElement.childNodes.item%28j%29.getAttribute%28%22colWidth%22%29%29%3B%20%7D%20%7D%20compressRate%3DeffectiveWidth/%28sumcol+MaxCols%29%3B%20if%28compressRate%3E%3D1%20%29%20%7B%20compressRate%3D1%3B%20%7D%20compressColWidth%28compressRate%29%3B%20%7D%20var%20hcompressRate%3D1%3B%20var%20t_outerHTMLbak%3Dt.outerHTML%3B%20if%28prnSet.compressHeight%3D%3D1%29%20%7B%20cur1%3D0%3B%20for%20%28var%20i%3DtabHead%3Bi%3ClngEndLine%3Bi++%29%20%7B%20cur1%3Dcur1+parseInt%28t.rows%28i%29.style.height%29%3B%20%7D%20hcompressRate%3D%28repHeight-tabBottom-tabTop-PageHeadHeight-PageCaudaHeight-heightTop-heightBottom%29/%28cur1+lngEndLine-tabHead%29%20%3B%20if%28hcompressRate%3E%3D1%20%29%20%7B%20hcompressRate%3D1%3B%20%7D%20compressRowHeight%28hcompressRate%2CtabHead%2ClngEndLine%29%3B%20%7D%20if%20%28prnSet.compressFont%21%3D1%29%20%7B%20var%20compressFont%3D0%3B%20if%28hcompressRate%3CcompressRate%29%20%7B%20compressFont%3DhcompressRate%3B%20%7D%20else%20%7B%20compressFont%3DcompressRate%3B%20%7D%20if%28compressFont%3C1%29%7B%20t.style.fontSize%3DparseFloat%28t.style.fontSize%29*compressFont%3B%20%7D%20%7D%20setAutoturnRow%28%29%3B%20cur1%3D0%3B%20for%20%28var%20i%3DtabHead%3Bi%3ClngEndLine%3Bi++%29%20%7B%20cur1%3Dcur1+parseInt%28t.rows%28i%29.style.height%29%3B%20if%20%28cur1%3E%3DrepHeight-tabBottom-tabTop-PageHeadHeight-PageCaudaHeight-heightTop-heightBottom%7C%7C%20i%3D%3DlngEndLine-1%29%7B%20if%20%28cur1%3D%3DrepHeight-tabBottom-tabTop-PageHeadHeight-PageCaudaHeight-heightTop-heightBottom%29%20%7B%20cur1%3D0%3B%20%7D%20else%20%7B%20cur1%3DparseInt%28t.rows%28i%29.style.height%29%3B%20%7D%20sumcol%3D0%3B%20var%20bFind%3Dfalse%3B%20iStart%3D0%3B%20iEnd%3D0%3B%20if%20%28i%3D%3DlngEndLine-1%29%7B%20perPageHTML%3DperPageHTML+t.rows%28i%29.outerHTML%20%3B%20%7D%20for%20%28var%20j%3D0%3Bj%3CMaxCols%3Bj++%29%7B%20if%20%28oXML1.documentElement.childNodes.item%28j%29.getAttribute%28%22colSelect%22%29%3D%3D%22block%22%29%7B%20sumcol%3Dsumcol+parseInt%28oXML1.documentElement.childNodes.item%28j%29.getAttribute%28%22colWidth%22%29%29*compressRate%3B%20%7D%20if%20%28sumcol%3E%3DeffectiveWidth%20%7C%7C%20j%3D%3DMaxCols-1%29%7B%20if%20%28sumcol%3C%3DeffectiveWidth%29%7B%20iEnd%3Dj%3B%20sumcol%3D0%3B%20%7D%20else%20%7B%20iEnd%3Dj-1%3B%20sumcol%3DparseInt%28oXML1.documentElement.childNodes.item%28j%29.getAttribute%28%22colWidth%22%29%29*compressRate%3B%20%7D%20var%20s1%3DHideCol%28strCol%2CiStart%2CiEnd%29%3B%20bFind%3Dtrue%3B%20PageDataAdd%28Pages%29%3B%20arrPage%5BPages%5D%3DhtmlTop+htmlBottom+tabstyle+s1%3B%20arrPage%5BPages%5D%3DarrPage%5BPages%5D+PageHeadHTML%3B%20arrPage%5BPages%5D%3DarrPage%5BPages%5D+perPageHTML+PageCaudaHTML+%22%3C/Table%3E%22%20+%22%3Cimg%20%3E%22%3B%20if%20%28i%3D%3DlngEndLine-1%29%7B%20if%28cur1%3ErepHeight-tabBottom-tabTop-PageHeadHeight-PageCaudaHeight-heightTop-heightBottom%29%7B%20PageDataAdd%28Pages+1%29%3B%20arrPage%5BPages+1%5D%3DhtmlTop+htmlBottom+tabstyle+s1%3B%20arrPage%5BPages+1%5D%3DarrPage%5BPages+1%5D+PageHeadHTML+PageCaudaHTML+%22%3C/Table%3E%22+%22%3Cimg%20%3E%22%3B%20biglabel.innerHTML%3Dbiglabel.innerHTML%20+%22%3Cdiv%20class%3DpreviewDiv%20%3E%u6B63%u5728%u8BA1%u7B97...%3C/DIV%3E%22%3B%20Pages%3DPages+1%3B%20%7D%20%7D%20biglabel.innerHTML%3Dbiglabel.innerHTML%20+%22%3Cdiv%20class%3DpreviewDiv%20%3E%u6B63%u5728%u8BA1%u7B97...%3C/DIV%3E%22%3B%20Pages%3DPages+1%3B%20if%20%28%28j%3D%3DMaxCols-1%20%29%20%26%26%20%28iEnd%3D%3Dj-1%29%20%29%7B%20var%20s1%3DHideCol%28strCol%2CMaxCols-1%2CMaxCols-1%29%3B%20bFind%3Dtrue%3B%20PageDataAdd%28Pages%29%3B%20arrPage%5BPages%5D%3DhtmlTop+htmlBottom+tabstyle+s1%3B%20arrPage%5BPages%5D%3DarrPage%5BPages%5D+PageHeadHTML%3B%20arrPage%5BPages%5D%3DarrPage%5BPages%5D+perPageHTML+PageCaudaHTML+%22%3C/Table%3E%22+%22%3Cimg%20%3E%22%3B%20if%20%28i%3D%3DlngEndLine-1%29%7B%20if%28cur1%3ErepHeight-tabBottom-tabTop-PageHeadHeight-PageCaudaHeight-heightTop-heightBottom%29%7B%20PageDataAdd%28Pages+1%29%3B%20arrPage%5BPages+1%5D%3DhtmlTop+htmlBottom+tabstyle+s1%20%3B%20arrPage%5BPages+1%5D%3DarrPage%5BPages+1%5D+PageHeadHTML+PageCaudaHTML+%22%3C/Table%3E%22+%22%3Cimg%20%3E%22%3B%20biglabel.innerHTML%3Dbiglabel.innerHTML%20+%22%3Cdiv%20class%3DpreviewDiv%20%3E%u6B63%u5728%u8BA1%u7B97...%3C/DIV%3E%22%3B%20Pages%3DPages+1%3B%20%7D%20%7D%20biglabel.innerHTML%3Dbiglabel.innerHTML%20+%22%3Cdiv%20class%3DpreviewDiv%20%3E%u6B63%u5728%u8BA1%u7B97...%3C/DIV%3E%22%3B%20Pages%3DPages+1%3B%20%7D%20iStart%3DiEnd+1%3B%20%7D%20%7D%20perPageHTML%3D%22%22%3B%20%7D%20perPageHTML%3DperPageHTML+t.rows%28i%29.outerHTML%20%3B%20%7D%20mdblRate%3D1%3B%20htmlTop%3D%22%22%3B%20htmlBottom%3D%22%22%3B%20t.outerHTML%3Dt_outerHTMLbak%3B%20t.style.display%3D%22none%22%3B%20for%28var%20i%3D0%3Bi%3CPages%3Bi++%29%7B%20arrPage%5Bi%5D%3Dfc_RepStr%28arrPage%5Bi%5D%2C%22%28P%29%22%2CPages+%22%22%29%3B%20%7D%20%7D%20";
				out.println(strX);
			}	





}



//下面是自定义的方法
//--------------------------------------
//两个结果集的示例,第一个用连接池打开,第二个用一般方式打开
private String twors() {
//	Node root = document.getChildNodes().item(0);
 //   String sField=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
  //  String sTable=root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
	String strSql="select flngVoucherID,fstrVoucherTypeName from Voucher" ;
	String sTmp="";
	try {
		Statement stmt = con.createStatement();
		rs = stmt.executeQuery(strSql);
		while (rs.next()) {
			String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; 
			String sConnStr = "jdbc:odbc:ereport"; 
			Class.forName(sDBDriver);
			Connection con1 = DriverManager.getConnection(sConnStr,"sa",""); 
			String sT=rs.getString(1);
			Statement stmt1 = con1.createStatement();
			rs1 = stmt1.executeQuery("select fstrAccountName from voucherdetail Where flngVoucherId="+sT);
			while (rs1.next()) {
				System.out.println("科目:"+rs1.getString(1));
			}		
		}		
	}	
	catch (Exception e){
		sTmp=e.getMessage() ;
	}
	return sTmp;
}
//--------------------------------------
private String fc_FieldToTable() {
	Node root = document.getChildNodes().item(0);
    String sField=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
    String sTable=root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
	String strSql="select "+sField+" From "+sTable ;
	String sTmp="";
	try {
		Statement stmt = con.createStatement();
		rs = stmt.executeQuery(strSql);
	}	
	catch (Exception e){
		sTmp=e.getMessage() ;
	}
	return sTmp;
}
//--------------------------------------
private String GetDB() {
		Node root = document.getChildNodes().item(0);
        String sConnect=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
        String sSql=root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
        sSql=fcTrans(sSql);
        //System.out.println(sSql);
        String sR="";
        String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; //建立数据库连接
		String sConnStr = "jdbc:odbc:"+sConnect ; 
		try {
			Class.forName(sDBDriver);
			con = DriverManager.getConnection(sConnStr,"sa",""); 
			Statement stmt = con.createStatement();
	
			rs = stmt.executeQuery(sSql);//执行查询建立结果集
			if (rs.next()) {
				sR=rs.getString(1);
			}
			rs.close();
			stmt.close();
		}
		catch (Exception e){
			sR=e.getMessage();
		}
		
		return sR;
}
//--------------------------------------
private String fc_select() {
	Node root = document.getChildNodes().item(0);
    String strSql=root.getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
    String strPageNo=root.getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
	int iPageNo=Integer.parseInt(strPageNo,10);//页号
    String strPageSize=root.getChildNodes().item(2).getChildNodes().item(0).getNodeValue();
	int iPageSize=Integer.parseInt(strPageSize,10);//页尺寸
	strSql=fcTrans(strSql);
	//System.out.println("fc_select:"+strSql);
	String strX = "<root>";
	String sTmp = "";
	int iField=1;
	int iCount=1;
	int i=1;
	try {
		Statement stmt = con.createStatement();
		rs = stmt.executeQuery(strSql);
        ResultSetMetaData rsmd=rs.getMetaData();
		while (rs.next()) {
			//每页30行
			if (i>(iPageNo-1)*iPageSize && i<=iPageNo*iPageSize) {
		        strX = strX + "<record>";
				iCount=rsmd.getColumnCount();
		        for (iField = 1 ; iField<=iCount ;iField++ ) 
				{
					//当有NULL字段名时,表示此则无需给值.用fcnull标记名区分.
					String colName=rsmd.getColumnName(iField);
					if (colName==null) {
						strX = strX + "<fcnull></fcnull>" ;
					}
					else {
						String sT=rs.getString(iField);
						if (sT==null) sT="";
			            strX = strX + "<fc>" + sT +"</fc>" ;
		            }
				}
		        strX = strX + "</record>";
	        }
	        i = i + 1;
		}
		i=i-1;
		if (i>0) {
			strX = strX + "<pages>"+i+"</pages>";
		}
		strX = strX + "</root>";
		rs.close();		
	}
	catch (Exception e){
		sTmp=e.getMessage() ;
		System.out.println(sTmp);
		e.printStackTrace();
	}
	
	return strX ;

}
//--------------------------------------
private String fc_select1() {
//将页号和页尺寸两个节点从第一个子节点和第二个子节点改为第一个子节点下的第一个子节点和第二个子节点
//将第二个子节点空出来给设置数据源用.
//第二个子节点下将有三个子节点:数据源名称,用户名,密码.
	Node root = document.getChildNodes().item(0);
    String strPageNo=root.getChildNodes().item(0).getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
	int iPageNo=Integer.parseInt(strPageNo,10);//页号
    String strPageSize=root.getChildNodes().item(0).getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
	int iPageSize=Integer.parseInt(strPageSize,10);//页尺寸
//数据源
    strDataSource=root.getChildNodes().item(1).getChildNodes().item(0).getChildNodes().item(0).getNodeValue();
    strUserName=root.getChildNodes().item(1).getChildNodes().item(1).getChildNodes().item(0).getNodeValue();
    try {
    	strPassword=root.getChildNodes().item(1).getChildNodes().item(2).getChildNodes().item(0).getNodeValue();
    }
    catch (Exception e){
    	strPassword="";
    }
//-------	

//多SQL查询
	String strX = "<root>";
	int ii=0;
	int i=1;
	//按顺序取出SQL节点
	for(ii=2;ii<root.getChildNodes().getLength();ii++){
		
	    String strSql=root.getChildNodes().item(ii).getChildNodes().item(0).getNodeValue();
		
		strX=strX+fc_selectTmp(iPageNo,iPageSize,i,strSql);
		
		i=iPosition;
	} //For循环结束
	i=i-1;
	if (i>0) {
		strX = strX + "<pages>"+i+"</pages>";
	}
	strX = strX + "</root>";
	
	return strX ;

}
//--------------------------------------
//计算一个SQL查询,供fc_select1 fc_select2类函数使用
private String fc_selectTmp(int iPageNo,int iPageSize,int iPos,String strSql) {
//iPageNo为起始页号,iPageSize为页尺寸,iPos为所有查询结果的行位置,strSql为要执行的SQL语句
//返回SQL语句的运行结果,结果为以<record>...</record>形式的XML串
//
	strSql=fcTrans(strSql);
	
	
	String sTmp = "";
	String strX = "";
	int iField=1;
	int iCount=1;
	int i=iPos;
	try {
		
		//String sDBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; 
		//String sConnStr = "jdbc:odbc:"+strDataSource; 
		//Class.forName(sDBDriver);
		Connection conTmp = ds.getConnection();
		
		Statement stmtTmp = conTmp.createStatement();
		ResultSet rsTmp = stmtTmp.executeQuery(strSql);
        ResultSetMetaData rsmdTmp=rsTmp.getMetaData();
		while (rsTmp.next()) {
			//每页30行
			if (i>(iPageNo-1)*iPageSize && i<=iPageNo*iPageSize) {
		        strX = strX + "<record>";
				iCount=rsmdTmp.getColumnCount();
		        for (iField = 1 ; iField<=iCount ;iField++ ) 
				{
					//当有NULL字段名时,表示此则无需给值.用fcnull标记名区分.
					String colName=rsmdTmp.getColumnName(iField);
					if (colName==null) {
						strX = strX + "<fcnull></fcnull>" ;

⌨️ 快捷键说明

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