import java.util.*;
import java.io.*;

public class F
{
   public static void main(String[] args)
   {
      PrintWriter out = new PrintWriter(System.out);
      new F(new FastScanner(), out);
      out.close();
   }

   // Down, Right, Up, Left
   int R, C;
   int[] dr = {1, 0, -1, 0};
   int[] dc = {0,  1, 0, -1};
   boolean[][] isBlocked;
   Integer[][][] memo;
   int go(int dir, int r, int c)
   {
      if (r < 0 || c < 0 || r >= R || c >= C) return 0;
      if (isBlocked[r][c]) return 0;
      if (memo[dir][r][c] != null) return memo[dir][r][c];
      return memo[dir][r][c] = 1+go(dir, r+dr[dir], c+dc[dir]);
   }

   public F(FastScanner in, PrintWriter out)
   {
      R = in.nextInt();
      C = in.nextInt();
      long res = 0;
      isBlocked = new boolean[R][C];
      memo = new Integer[4][R][C];
      for (int i=0; i<R; i++)
      {
         String s = in.next();
         for (int j=0; j<C; j++)
            isBlocked[i][j] = s.charAt(j) == '#';
      }

      for (int i=1; i+1<R; i++)
         if (go(1, i, 0) == C) res++;
      for (int j=1; j+1<C; j++)
         if (go(0, 0, j) == R) res++;

      for (int j=1; j+1<C; j++)
      {
         boolean lastLeft = false;
         boolean lastRight = false;

         int numLeft = 0, numRight = 0;
         for (int i=1; i+1<R; i++)
         {
            if (isBlocked[i][j])
            {
               numLeft = 0;
               numRight = 0;
               continue;
            }

            boolean canLeft = go(3, i, j) == j+1;
            boolean canDown = go(0, i, j) == (R-i);
            boolean canRight = go(1, i, j) == (C-j);

            if (canLeft)
               res += numLeft+numRight+(lastLeft?-1:0);
            if (canRight)
               res += numLeft+numRight+(lastRight?-1:0);

            if (canLeft) numLeft++;
            if (canRight) numRight++;

            lastLeft = canLeft;
            lastRight = canRight;
         }
      }

      for (int i=1; i+1<R; i++)
      {
         boolean lastUp = false;
         boolean lastDown = false;
         int numDown=0, numRight=isBlocked[i][C-1] ? 0 : 1, numUp=0;
         for (int j=C-2; j>0; j--)
         {
            if (isBlocked[i][j])
            {
               numDown = 0;
               numRight = 0;
               numUp = 0;
               continue;
            }

            boolean canUp = go(2, i, j) == (i+1);
            boolean canDown = go(0, i, j) == (R-i);
            boolean canLeft = go(3, i, j) == (j+1);

            if (canUp)
            {
               res += numUp+numDown+numRight+(lastUp ? -1 : 0);
               if (canLeft) res++;
            }
            if (canDown)
            {
               res += numUp+numDown+numRight+(lastDown ? -1 : 0);
               if (canLeft) res++;
            }
            if (canUp) numUp++;
            if (canDown) numDown++;

            lastUp = canUp;
            lastDown = canDown;
         }
      }

      out.println(res);
   }
}

class FastScanner{
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;

    public FastScanner()
    {
        stream = System.in;
    }

    int read()
    {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars){
            curChar = 0;
            try{
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    boolean isSpaceChar(int c)
    {
        return c==' '||c=='\n'||c=='\r'||c=='\t'||c==-1;
    }

    boolean isEndline(int c)
    {
        return c=='\n'||c=='\r'||c==-1;
    }

    int nextInt()
    {
        return Integer.parseInt(next());
    }

    long nextLong()
    {
        return Long.parseLong(next());
    }

    double nextDouble()
    {
        return Double.parseDouble(next());
    }

    String next(){
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do{
            res.appendCodePoint(c);
            c = read();
        }while(!isSpaceChar(c));
        return res.toString();
    }

    String nextLine(){
        int c = read();
        while (isEndline(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do{
            res.appendCodePoint(c);
            c = read();
        }while(!isEndline(c));
        return res.toString();
    }
}


import java.util.*;
import java.io.*;

public class F
{
   public static void main(String[] args)
   {
      PrintWriter out = new PrintWriter(System.out);
      new F(new FastScanner(), out);
      out.close();
   }

   // Down, Right, Up, Left
   int R, C;
   int[] dr = {1, 0, -1, 0};
   int[] dc = {0,  1, 0, -1};
   boolean[][] isBlocked;
   Integer[][][] memo;
   int go(int dir, int r, int c)
   {
      if (r < 0 || c < 0 || r >= R || c >= C) return 0;
      if (isBlocked[r][c]) return 0;
      if (memo[dir][r][c] != null) return memo[dir][r][c];
      return memo[dir][r][c] = 1+go(dir, r+dr[dir], c+dc[dir]);
   }

   public F(FastScanner in, PrintWriter out)
   {
      R = in.nextInt();
      C = in.nextInt();
      long res = 0;
      isBlocked = new boolean[R][C];
      memo = new Integer[4][R][C];
      for (int i=0; i<R; i++)
      {
         String s = in.next();
         for (int j=0; j<C; j++)
            isBlocked[i][j] = s.charAt(j) == '#';
      }

      for (int i=1; i+1<R; i++)
         if (go(1, i, 0) == C) res++;
      for (int j=1; j+1<C; j++)
         if (go(0, 0, j) == R) res++;

      for (int j=1; j+1<C; j++)
      {
         boolean lastLeft = false;
         boolean lastRight = false;

         int numLeft = 0, numRight = 0;
         for (int i=1; i+1<R; i++)
         {
            if (isBlocked[i][j])
            {
               numLeft = 0;
               numRight = 0;
               lastLeft = false;
               lastRight = false;
               continue;
            }

            boolean canLeft = go(3, i, j) == j+1;
            boolean canDown = go(0, i, j) == (R-i);
            boolean canRight = go(1, i, j) == (C-j);

            if (canLeft)
               res += numLeft+numRight+(lastLeft?-1:0);
            if (canRight)
               res += numLeft+numRight+(lastRight?-1:0);

            if (canLeft) numLeft++;
            if (canRight) numRight++;

            lastLeft = canLeft;
            lastRight = canRight;
         }
      }

      for (int i=1; i+1<R; i++)
      {
         boolean lastUp = false;
         boolean lastDown = false;
         int numDown=0, numRight=isBlocked[i][C-1] ? 0 : 1, numUp=0;
         for (int j=C-2; j>0; j--)
         {
            if (isBlocked[i][j])
            {
               numDown = 0;
               numRight = 0;
               numUp = 0;
               lastUp = false;
               lastDown = false;
               continue;
            }

            boolean canUp = go(2, i, j) == (i+1);
            boolean canDown = go(0, i, j) == (R-i);
            boolean canLeft = go(3, i, j) == (j+1);

            if (canUp)
            {
               res += numUp+numDown+numRight+(lastUp ? -1 : 0);
               if (canLeft) res++;
            }
            if (canDown)
            {
               res += numUp+numDown+numRight+(lastDown ? -1 : 0);
               if (canLeft) res++;
            }
            if (canUp) numUp++;
            if (canDown) numDown++;

            lastUp = canUp;
            lastDown = canDown;
         }
      }

      out.println(res);
   }
}

class FastScanner{
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;

    public FastScanner()
    {
        stream = System.in;
    }

    int read()
    {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars){
            curChar = 0;
            try{
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    boolean isSpaceChar(int c)
    {
        return c==' '||c=='\n'||c=='\r'||c=='\t'||c==-1;
    }

    boolean isEndline(int c)
    {
        return c=='\n'||c=='\r'||c==-1;
    }

    int nextInt()
    {
        return Integer.parseInt(next());
    }

    long nextLong()
    {
        return Long.parseLong(next());
    }

    double nextDouble()
    {
        return Double.parseDouble(next());
    }

    String next(){
        int c = read();
        while (isSpaceChar(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do{
            res.appendCodePoint(c);
            c = read();
        }while(!isSpaceChar(c));
        return res.toString();
    }

    String nextLine(){
        int c = read();
        while (isEndline(c))
            c = read();
        StringBuilder res = new StringBuilder();
        do{
            res.appendCodePoint(c);
            c = read();
        }while(!isEndline(c));
        return res.toString();
    }
}


import java.io.*;
import java.util.*;
import java.math.BigInteger;

public class Main{
    final boolean isFileIO =  false;
    BufferedReader in;
    PrintWriter out;
    StringTokenizer st = new StringTokenizer("");
    String delim = " ";

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.initIO();
        m.solve();
        m.in.close();
        m.out.close();
    }

    public void initIO() throws IOException {
        if(!isFileIO) {
            in = new BufferedReader(new InputStreamReader(System.in));
            out = new PrintWriter(System.out);
        } else {
            in = new BufferedReader(new FileReader("input.txt"));
            out = new PrintWriter("output.txt");
        }
    }

    String nt() throws IOException {
        if(!st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken(delim);
    }

    String rl() throws IOException {
        return in.readLine();
    }

    int ni() throws IOException {
        return Integer.parseInt(nt());
    }

    long nl() throws IOException {
        return Long.parseLong(nt());
    }

    double nd() throws IOException {
        return Double.parseDouble(nt());
    }

    class Pair {
        public long x;
        public long y;

        public Pair(long x, long y) {
            this.x = x;
            this.y = y;
        }

        public String toString() {
            return String.format("{%d, %d}", x, y);
        }
    }

    public void solve() throws IOException {
        int n, m;
        n = ni(); m = ni();
        String[] s = new String[n];
        for(int i = 0; i < n; i++) {
            s[i] = rl();
        }
        int[][] rowBar = new int[n][m + 1];
        for(int i = 0; i < n; i++) {
            for(int j = 1; j <= m; j++) {
                rowBar[i][j] = rowBar[i][j - 1] + (s[i].charAt(j - 1) == '#' ? 1 : 0);
            }
        }
        int[][] colBar = new int[m][n + 1];
        for(int i = 0; i < m; i++) {
            for(int j = 1; j <= n; j++) {
                colBar[i][j] = colBar[i][j - 1] + (s[j - 1].charAt(i) == '#' ? 1 : 0);
            }
        }
        int[][] colCnt = new int[m + 1][n + 1];
        for(int i = 1; i <= n; i++) {
            for(int j = 1; j <= m; j++) {
                colCnt[j][i] = colCnt[j - 1][i] + (colBar[j - 1][i] > 0 ? 1 : 0);
            }
        }
        int[][] rowCnt = new int[n + 1][m + 1];
        for(int i = 1; i <= m; i++) {
            for(int j = 1; j <= n; j++) {
                rowCnt[j][i] = rowCnt[j - 1][i] + (rowBar[j - 1][i] > 0 ? 1 : 0);
            }
        }
        int[][] colCntDown = new int[m + 1][n + 1];
        for(int i = n; i >= 1; i--) {
            for(int j = 1; j <= m; j++) {
                colCntDown[j][i] = colCntDown[j - 1][i] + (colBar[j - 1][n] - colBar[j - 1][i - 1] == 0 ? 1 : 0);
            }
        }
        int[][] rowCntDown = new int[n + 1][m + 1];
        for(int i = m; i >= 1; i--) {
            for(int j = 1; j <= n; j++) {
                rowCntDown[j][i] = rowCntDown[j - 1][i] + (rowBar[j - 1][m] - rowBar[j - 1][i - 1] == 0 ? 1 : 0);
            }
        }
        long ans = 0;
        //UP LEFT, DOWN LEFT
        for(int i = 1; i < n - 1; i++) {
            for(int j = 1; j < m - 1; j++) {
                if(rowBar[i][j + 1] == 0 && (colBar[j][n] - colBar[j][i]) == 0) {
                    ans++;
                }
                if(rowBar[i][j + 1] == 0 && colBar[j][i + 1] == 0) {
                    ans++;
                }
            }
        }
        //UP RIGHT, DOWN RIGHT
        for(int i = 1; i < n - 1; i++) {
            for(int j = 1; j < m - 1; j++) {
                if((rowBar[i][m] - rowBar[i][j]) == 0 && colBar[j][i + 1] == 0) {
                    ans++;
                }
                if((rowBar[i][m] - rowBar[i][j]) == 0 && (colBar[j][n] - colBar[j][i]) == 0) {
                    ans++;
                }
            }
        }
        for(int i = 1; i < m - 1; i++) {
            for(int j = 1; j < n - 1; j++) {
                if(colBar[i][j + 1] > 0) {
                    break;
                }
                int left, right, mid;
                left = 2; right = i + 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    int cnt = rowBar[j][i + 1] - rowBar[j][mid - 1];
                    if(cnt > 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if((i + 1) - left > 0) {
                    ans += colCntDown[i][j + 1] - colCntDown[left - 1][j + 1];
                }
                left = i + 1; right = m - 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    int cnt = rowBar[j][mid] - rowBar[j][i];
                    if(cnt <= 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if(rowBar[j][left] - rowBar[j][i] > 0) {
                    left--;
                }
                if(left - (i + 1) > 0) {
                    ans += colCntDown[left][j + 1] - colCntDown[i + 1][j + 1];
                }
            }
            ans += (colBar[i][n] == 0 ? 1 : 0);
        }
        for(int i = 1; i < n - 1; i++) {
            for(int j = 1; j < m - 1; j++) {
                if(rowBar[i][j + 1] > 0) {
                    break;
                }

                int left, right, mid;
                left = 2; right = i + 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    int cnt = colBar[j][i + 1] - colBar[j][mid - 1];
                    if(cnt > 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if((i + 1) - left > 0) {
                    ans += rowCntDown[i][j + 1] - rowCntDown[left - 1][j + 1];
                }
                left = i + 1; right = n - 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    int cnt = colBar[j][mid] - colBar[j][i];
                    if(cnt <= 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if(colBar[j][left] - colBar[j][i] > 0) {
                    left--;
                }
                if(left - (i + 1) > 0) {
                    ans += rowCntDown[left][j + 1] - rowCntDown[i + 1][j + 1];
                }

            }
            ans += (rowBar[i][m] == 0 ? 1 : 0);
        }
        for(int i = 1; i < m - 3; i++) {
            for(int j = 1; j < n - 1; j++) {
                int left, right, mid;
                left = i + 1; right = m - 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    if(rowBar[j][mid] - rowBar[j][i] <= 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if(rowBar[j][left] - rowBar[j][i] > 0) {
                    left--;
                }
                if(left - i < 3) {
                   continue;
                }
                if(colBar[i][j + 1] == 0) {
                    ans += (left - (i + 2)) - (colCnt[left][j + 1] - colCnt[i + 2][j + 1]);
                }
                if(colBar[i][n] - colBar[i][j] == 0) {
                    ans += colCntDown[left][j + 1] - colCntDown[i + 2][j + 1];
                }

            }
        }
        for(int i = 1; i < n - 3; i++) {
            for(int j = 1; j < m - 1; j++) {
                int left, right, mid;
                left = i + 1; right = n - 1; mid = 0;
                while(left < right) {
                    mid = left + (right - left) / 2;
                    if(colBar[j][mid] - colBar[j][i] <= 0) {
                        left = mid + 1;
                    } else {
                        right = mid;
                    }
                }
                if(colBar[j][left] - colBar[j][i] > 0) {
                    left--;
                }
                if(left - i < 3) {
                    continue;
                }
                if(rowBar[i][j + 1] == 0) {
                    ans += (left - (i + 2)) - (rowCnt[left][j + 1] - rowCnt[i + 2][j + 1]);
                }
                if(rowBar[i][m] - rowBar[i][j] == 0) {
                    ans += rowCntDown[left][j + 1] - rowCntDown[i + 2][j + 1];
                }
            }
        }
        out.println(ans);
    }
}

class Utils {

    public static long binpow(long a, long exp, long mod) {
        if(exp == 0) {
            return 1;
        }
        if(exp % 2 == 0) {
            long temp = binpow(a, exp / 2, mod);
            return (temp * temp) % mod;
        } else {
            return (binpow(a, exp - 1, mod) * a) % mod;
        }
    }

    public static long inv(long a, long mod) {
        return binpow(a, mod - 2, mod);
    }

    public static long addmod(long a, long b, long mod) {
        return ((a + b) % mod + mod) % mod;
    }

    public static long gcd(long a, long b) {
        if(b == 0)
            return a;
        return gcd(b, a % b);
    }

    //mul must be < 10^18
    public static long mulmod(long a, long b, long mod) {
        return (a * b + (((a * b) / mod) + 1) * mod) % mod;
    }
}


//package round293;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class F {
	InputStream is;
	PrintWriter out;
	String INPUT = "";

	void solve()
	{
		int n = ni(), m = ni();
		char[][] map = nm(n,m);
		int[][] up = go(map);
		map = revud(map);
		int[][] down = revud(go(map));
		map = revud(map);
		map = trans(map);
		int[][] left = trans(go(map));
		map = revud(map);
		int[][] right = trans(revud(go(map)));
		map = revud(map);
		map = trans(map);

		long ret = 0;

		// 0
		for(int i = 1;i < m-1;i++){
			if(down[0][i] == 1)ret++;
		}
		for(int i = 1;i < n-1;i++){
			if(right[i][0] == 1)ret++;
		}

		// 1
		for(int i = 1;i < n-1;i++){
			for(int j = 1;j < m-1;j++){
				if(left[i][j] == 1 && up[i][j] == 1)ret++;
				if(left[i][j] == 1 && down[i][j] == 1)ret++;
				if(right[i][j] == 1 && up[i][j] == 1)ret++;
				if(right[i][j] == 1 && down[i][j] == 1)ret++;
			}
		}

		// 2
		for(int i = 1;i < n-1;i++){
			// up up
			{
				int count = 0;
				for(int j = 1;j < m-1;j++){
					if(j-2 >= 1 && up[i][j-2] == 1 && map[i][j-1] != '#')count++;
					if(map[i][j] == '#')count = 0;
					if(up[i][j] == 1)ret += count;
				}
			}
			// down down
			{
				int count = 0;
				for(int j = 1;j < m-1;j++){
					if(j-2 >= 1 && down[i][j-2] == 1 && map[i][j-1] != '#')count++;
					if(map[i][j] == '#')count = 0;
					if(down[i][j] == 1)ret += count;
				}
			}
			// up down
			{
				int count = 0;
				for(int j = 1;j < m-1;j++){
					if(j-1 >= 1 && up[i][j-1] == 1)count++;
					if(map[i][j] == '#')count = 0;
					if(down[i][j] == 1)ret += count;
				}
			}
			{
				int count = 0;
				for(int j = 1;j < m-1;j++){
					if(j-1 >= 1 && down[i][j-1] == 1)count++;
					if(map[i][j] == '#')count = 0;
					if(up[i][j] == 1)ret += count;
				}
			}
		}
		for(int i = 1;i < m-1;i++){
			// up up
			{
				int count = 0;
				for(int j = 1;j < n-1;j++){
					if(j-2 >= 1 && left[j-2][i] == 1 && map[j-1][i] != '#')count++;
					if(map[j][i] == '#')count = 0;
					if(left[j][i] == 1)ret += count;
				}
			}
			// down down
			{
				int count = 0;
				for(int j = 1;j < n-1;j++){
					if(j-2 >= 1 && right[j-2][i] == 1 && map[j-1][i] != '#')count++;
					if(map[j][i] == '#')count = 0;
					if(right[j][i] == 1)ret += count;
				}
			}
			// up down
			{
				int count = 0;
				for(int j = 1;j < n-1;j++){
					if(j-1 >= 1 && left[j-1][i] == 1)count++;
					if(map[j][i] == '#')count = 0;
					if(right[j][i] == 1)ret += count;
				}
			}
			{
				int count = 0;
				for(int j = 1;j < n-1;j++){
					if(j-1 >= 1 && right[j-1][i] == 1)count++;
					if(map[j][i] == '#')count = 0;
					if(left[j][i] == 1)ret += count;
				}
			}
		}
		out.println(ret);
	}

	int[][] go(char[][] map)
	{
		int n = map.length;
		int m = map[0].length;
		int[][] up = new int[n][m];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				up[i][j] = map[i][j] == '#' ? 0 : i == 0 ? 1 : up[i-1][j];
			}
		}
		return up;
	}

	// 上下左右のcountをとって、本来の位置になるように回転させるやつ
	//	int[][] br = countBR(b);
	//	revlr(b);
	//	int[][] bl = countBR(b);
	//	revud(b);
	//	int[][] tl = countBR(b);
	//	revlr(b);
	//	int[][] tr = countBR(b);
	//
	//	revlr(bl);
	//	revud(tr);
	//	revlr(revud(tl));
	//	revud(b);

	public static int[][] revlr(int[][] a)
	{
		for(int i = 0;i < a.length;i++){
			for(int j = 0, k = a[i].length-1;j < k;j++,k--){
				int d = a[i][j]; a[i][j] = a[i][k]; a[i][k] = d;
			}
		}
		return a;
	}

	public static char[][] revlr(char[][] a)
	{
		for(int i = 0;i < a.length;i++){
			for(int j = 0, k = a[i].length-1;j < k;j++,k--){
				char d = a[i][j]; a[i][j] = a[i][k]; a[i][k] = d;
			}
		}
		return a;
	}

	public static int[][] revud(int[][] a)
	{
		for(int i = 0, j = a.length-1;i < j;i++,j--){
			int[] d = a[i]; a[i] = a[j]; a[j] = d;
		}
		return a;
	}

	public static char[][] revud(char[][] a)
	{
		for(int i = 0, j = a.length-1;i < j;i++,j--){
			char[] d = a[i]; a[i] = a[j]; a[j] = d;
		}
		return a;
	}

	public static int[][] trans(int[][] a)
	{
		int n = a.length, m = a[0].length;
		int[][] t = new int[m][n];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				t[j][i] = a[i][j];
			}
		}
		return t;
	}

	public static char[][] trans(char[][] a)
	{
		int n = a.length, m = a[0].length;
		char[][] t = new char[m][n];
		for(int i = 0;i < n;i++){
			for(int j = 0;j < m;j++){
				t[j][i] = a[i][j];
			}
		}
		return t;
	}

	void run() throws Exception
	{
		is = oj ? System.in : new ByteArrayInputStream(INPUT.getBytes());
		out = new PrintWriter(System.out);

		long s = System.currentTimeMillis();
		solve();
		out.flush();
		tr(System.currentTimeMillis()-s+"ms");
	}

	public static void main(String[] args) throws Exception { new F().run(); }

	private byte[] inbuf = new byte[1024];
	private int lenbuf = 0, ptrbuf = 0;

	private int readByte()
	{
		if(lenbuf == -1)throw new InputMismatchException();
		if(ptrbuf >= lenbuf){
			ptrbuf = 0;
			try { lenbuf = is.read(inbuf); } catch (IOException e) { throw new InputMismatchException(); }
			if(lenbuf <= 0)return -1;
		}
		return inbuf[ptrbuf++];
	}

	private boolean isSpaceChar(int c) { return !(c >= 33 && c <= 126); }
	private int skip() { int b; while((b = readByte()) != -1 && isSpaceChar(b)); return b; }

	private double nd() { return Double.parseDouble(ns()); }
	private char nc() { return (char)skip(); }

	private String ns()
	{
		int b = skip();
		StringBuilder sb = new StringBuilder();
		while(!(isSpaceChar(b))){ // when nextLine, (isSpaceChar(b) && b != ' ')
			sb.appendCodePoint(b);
			b = readByte();
		}
		return sb.toString();
	}

	private char[] ns(int n)
	{
		char[] buf = new char[n];
		int b = skip(), p = 0;
		while(p < n && !(isSpaceChar(b))){
			buf[p++] = (char)b;
			b = readByte();
		}
		return n == p ? buf : Arrays.copyOf(buf, p);
	}

	private char[][] nm(int n, int m)
	{
		char[][] map = new char[n][];
		for(int i = 0;i < n;i++)map[i] = ns(m);
		return map;
	}

	private int[] na(int n)
	{
		int[] a = new int[n];
		for(int i = 0;i < n;i++)a[i] = ni();
		return a;
	}

	private int ni()
	{
		int num = 0, b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private long nl()
	{
		long num = 0;
		int b;
		boolean minus = false;
		while((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-'));
		if(b == '-'){
			minus = true;
			b = readByte();
		}

		while(true){
			if(b >= '0' && b <= '9'){
				num = num * 10 + (b - '0');
			}else{
				return minus ? -num : num;
			}
			b = readByte();
		}
	}

	private boolean oj = System.getProperty("ONLINE_JUDGE") != null;
	private void tr(Object... o) { if(!oj)System.out.println(Arrays.deepToString(o)); }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4 };
			int[] inCols = new int[] { 3, 2, 5 };
			String[][] games = new String[][] { { "...", "..#", "..." }, { "..", "..", "..", ".." },
					{ "#...#", "#...#", "###.#", "###.#" } };

			for (int i = 0; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 2; i < g.length; i++) {
				g[i] = br.readLine();
			}
			parseGame(g);
			solve();
		}

	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 =Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					cnt += isHorizontallyFree(j2, 0, i);
				}
				for (int j2 =Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					contiguousFree[LEFT_SIDE][j2][i] = cnt;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					cnt += isHorizontallyFree(j2, i, colsCnt-1);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					contiguousFree[RIGHT_SIDE][j2][i] = cnt;
				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					cnt += isVerticallyFree(j2, 0, i);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					contiguousFree[TOP_SIDE][i][j2] = cnt;
				}
			}
		}

		// bottom
		for (int i = rowsCnt -1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					cnt += isVerticallyFree(j2, i, rowsCnt-1);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					contiguousFree[BOTTOM_SIDE][i][j2] = cnt;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		return contiguousFree[side][r][c];
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4 };
			int[] inCols = new int[] { 3, 2, 5 };
			String[][] games = new String[][] { { "...", "..#", "..." }, { "..", "..", "..", ".." },
					{ "#...#", "#...#", "###.#", "###.#" } };

			for (int i = 0; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 0; i < g.length; i++) {
				g[i] = br.readLine();
			}
			parseGame(g);
			solve();
		}

	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE) - 1;
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE) - 1;
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == 0 || contiguousFree[LEFT_SIDE][j][i - 1] >= 1)) {
					contiguousFree[3][j][i] = 1;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == colsCnt - 1 || contiguousFree[RIGHT_SIDE][j][i + 1] >= 1)) {
					contiguousFree[RIGHT_SIDE][j][i] = 1;

				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == 0 || contiguousFree[TOP_SIDE][i - 1][j] > 0)) {
					contiguousFree[TOP_SIDE][i][j] = 1;
				}
			}
		}

		// bottom
		for (int i = rowsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == rowsCnt - 1 || contiguousFree[BOTTOM_SIDE][i + 1][j] > 0)) {
					contiguousFree[BOTTOM_SIDE][i][j] = 1;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		int ans = 0;
		if (side == LEFT_SIDE || side == RIGHT_SIDE) {
			for (int i = r + 1; i < rowsCnt; i++) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
			for (int i = r; i >= 0; i--) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
		} else {
			for (int i = c + 1; i < colsCnt; i++) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
			for (int i = c; i >= 0; i--) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
		}

		return ans;
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4, 5 };
			int[] inCols = new int[] { 3, 2, 5, 5 };
			String[][] games = new String[][] { { "...", "#.#", "..." }, { "..", "..", "..", ".." },
					{ "..#..", "..###", ".##..", "..#.." },

					{ "....#", ".....", "..#..", "##.##", "....."

					} };

			for (int i = 3; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve2();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 0; i < g.length; i++) {
				g[i] = br.readLine();
			}
			parseGame(g);
			solve2();
		}

	}

	static long countRowSegment(int r, int c1, int c2) {
		if (c1 > c2) {
			return countRowSegment(r, c2, c1);
		}
		c1 = Math.max(1, c1);
		c2 = Math.min(colsCnt - 2, c2);
		int up = 0;
		int down = 0;
		int both = 0;
		long ans = 0;
		int lastUp = 0;
		int lastDown = 0;
		for (int i = c1; i <= c2; i++) {
			int u = isVerticallyFree(i, 0, r);
			int d = isVerticallyFree(i, r, rowsCnt - 1);
			both += (u + d) == 2 ? 1 : 0;
			up += u;
			down += d;
			ans -= (lastUp + u) / 2;
			ans -= (lastDown + d) / 2;
			lastUp = u;
			lastDown = d;
		}
		ans += down * up - both;
		ans += (up * (up - 1)) / 2;
		ans += (down * (down - 1)) / 2;
		return ans;
	}

	static long countColSegment(int c, int r1, int r2) {
		if (r1 > r2) {
			return countColSegment(c, r2, r1);
		}
		r1 = Math.max(1, r1);
		r2 = Math.min(rowsCnt - 2, r2);
		int left = 0;
		int right = 0;
		int both = 0;
		long ans = 0;
		int lastLeft = 0;
		int lastRight = 0;
		for (int i = r1; i <= r2; i++) {
			int l = isHorizontallyFree(i, 0, c);
			int r = isHorizontallyFree(i, c, colsCnt - 1);
			both += (l + r) == 2 ? 1 : 0;
			left += l;
			right += r;
			ans -= (lastLeft + l) / 2;
			ans -= (lastRight + r) / 2;
			lastLeft = l;
			lastRight = r;
		}
		ans += right * left - both;
		ans += (left * (left - 1)) / 2;
		ans += (right * (right - 1)) / 2;
		return ans;
	}

	static void solve2() {
		long ans = 0;
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			m.add(-1);
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			m.add(colsCnt);
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			m.add(-1);
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			m.add(rowsCnt);
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		for (int i = 1; i < rowsCnt - 1; i++) {
			for (int k = 0; k < blockedRows[i].length - 1; k++) {
				ans += countRowSegment(i, blockedRows[i][k] + 1, blockedRows[i][k + 1] - 1);
			}
		}
		for (int i = 1; i < colsCnt - 1; i++) {
			for (int k = 0; k < blockedCols[i].length - 1; k++) {
				ans += countColSegment(i, blockedCols[i][k] + 1, blockedCols[i][k + 1] - 1);
			}
		}
		for (int i = 1; i < rowsCnt - 1; i++) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j]) {
					int t = isVerticallyFree(j, 0, i);
					int b = isVerticallyFree(j, i, rowsCnt - 1);
					int l = isHorizontallyFree(i, 0, j);
					int r = isHorizontallyFree(i, j, colsCnt - 1);
					ans += l * b + l * t + r * t + r * b;
				}
			}
		}

		for (int i = 1; i < rowsCnt - 1; i++) {
			ans += isHorizontallyFree(i, 0, colsCnt - 1);
		}

		for (int i = 1; i < colsCnt - 1; i++) {
			ans += isVerticallyFree(i, 0, rowsCnt - 1);
		}

		System.out.println(ans);
	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), rowsCnt - 1); j2++) {
					cnt += isHorizontallyFree(j2, 0, i);
				}
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), rowsCnt - 1); j2++) {
					contiguousFree[LEFT_SIDE][j2][i] = cnt;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), rowsCnt - 1); j2++) {
					cnt += isHorizontallyFree(j2, i, colsCnt - 1);
				}
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), rowsCnt - 1); j2++) {
					contiguousFree[RIGHT_SIDE][j2][i] = cnt;
				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), colsCnt - 1); j2++) {
					cnt += isVerticallyFree(j2, 0, i);
				}
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), colsCnt - 1); j2++) {
					contiguousFree[TOP_SIDE][i][j2] = cnt;
				}
			}
		}

		// bottom
		for (int i = rowsCnt - 1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), colsCnt - 1); j2++) {
					cnt += isVerticallyFree(j2, i, rowsCnt - 1);
				}
				for (int j2 = Math.max(blocked.get(j) + 1, 1); j2 < Math.min(blocked.get(j + 1), colsCnt - 1); j2++) {
					contiguousFree[BOTTOM_SIDE][i][j2] = cnt;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		return contiguousFree[side][r][c];
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4 };
			int[] inCols = new int[] { 3, 2, 5 };
			String[][] games = new String[][] { { "...", "..#", "..." }, { "..", "..", "..", ".." },
					{ "#...#", "#...#", "###.#", "###.#" } };

			for (int i = 0; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 0; i < g.length; i++) {
				g[i] = br.readLine();
			}
			parseGame(g);
			solve();
		}

	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == 0 || contiguousFree[LEFT_SIDE][j][i - 1] >= 1)) {
					contiguousFree[3][j][i] = 1;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == colsCnt - 1 || contiguousFree[RIGHT_SIDE][j][i + 1] >= 1)) {
					contiguousFree[RIGHT_SIDE][j][i] = 1;

				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == 0 || contiguousFree[TOP_SIDE][i - 1][j] > 0)) {
					contiguousFree[TOP_SIDE][i][j] = 1;
				}
			}
		}

		// bottom
		for (int i = rowsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == rowsCnt - 1 || contiguousFree[BOTTOM_SIDE][i + 1][j] > 0)) {
					contiguousFree[BOTTOM_SIDE][i][j] = 1;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		int ans = 0;
		if (side == LEFT_SIDE || side == RIGHT_SIDE) {
			for (int i = r + 1; i < rowsCnt; i++) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
			for (int i = r; i >= 0; i--) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
		} else {
			for (int i = c + 1; i < colsCnt; i++) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
			for (int i = c; i >= 0; i--) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
		}

		return ans;
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4 };
			int[] inCols = new int[] { 3, 2, 5 };
			String[][] games = new String[][] { { "...", "..#", "..." }, { "..", "..", "..", ".." },
					{ "#...#", "#...#", "###.#", "###.#" } };

			for (int i = 0; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 0; i < g.length; i++) {
				g[i] = br.readLine();
			}
			parseGame(g);
			solve();
		}

	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE);
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 =Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					cnt += isHorizontallyFree(j2, 0, i);
				}
				for (int j2 =Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					contiguousFree[LEFT_SIDE][j2][i] = cnt;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedCols[i].length; j++) {
				blocked.add(blockedCols[i][j]);
			}
			blocked.add(rowsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					cnt += isHorizontallyFree(j2, i, colsCnt-1);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), rowsCnt-1); j2++) {
					contiguousFree[RIGHT_SIDE][j2][i] = cnt;
				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size()-1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					cnt += isVerticallyFree(j2, 0, i);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					contiguousFree[TOP_SIDE][i][j2] = cnt;
				}
			}
		}

		// bottom
		for (int i = rowsCnt -1; i >= 0; i--) {
			List<Integer> blocked = new ArrayList<Integer>();
			blocked.add(-1);
			for (int j = 0; j < blockedRows[i].length; j++) {
				blocked.add(blockedRows[i][j]);
			}
			blocked.add(colsCnt);
			for (int j = 0; j < blocked.size() - 1; j++) {
				int cnt = 0;
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					cnt += isVerticallyFree(j2, i, rowsCnt-1);
				}
				for (int j2 = Math.max(blocked.get(j)+1,1); j2 < Math.min(blocked.get(j+1), colsCnt-1); j2++) {
					contiguousFree[BOTTOM_SIDE][i][j2] = cnt;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		return contiguousFree[side][r][c];
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class F {
	static boolean DEBUG = false;
	static InputStreamReader isr = new InputStreamReader(System.in);
	static BufferedReader br = new BufferedReader(isr);

	static int[] readIntArray() throws IOException {
		String[] v = br.readLine().split(" ");
		int[] ans = new int[v.length];

		for (int i = 0; i < ans.length; i++) {
			ans[i] = Integer.valueOf(v[i]);
		}

		return ans;
	}

	static int rowsCnt, colsCnt;
	static boolean[][] game;
	static int TOP_SIDE = 0;
	static int RIGHT_SIDE = 1;
	static int BOTTOM_SIDE = 2;
	static int LEFT_SIDE = 3;
	static int[][] blockedRows;
	static int[][] blockedCols;
	static int[][][] contiguousFree;

	public static void main(String[] args) throws IOException {

		if (DEBUG) {
			int[] inRows = new int[] { 3, 4, 4 };
			int[] inCols = new int[] { 3, 2, 5 };
			String[][] games = new String[][] { { "...", "..#", "..." }, { "..", "..", "..", ".." },
					{ "#...#", "#...#", "###.#", "###.#" } };

			for (int i = 0; i < games.length; i++) {
				rowsCnt = inRows[i];
				colsCnt = inCols[i];
				parseGame(games[i]);
				solve();
			}
		} else {
			int[] l = readIntArray();
			rowsCnt = l[0];
			colsCnt = l[1];
			String[] g = new String[rowsCnt];
			for (int i = 0; i < g.length; i++) {
				g[i] = br.readLine();
			}
			solve();
		}

	}

	static void solve() {
		long ans = 0;

		precompute();

		// opposing left
		if (colsCnt <= 2) {
			for (int i = 1; i < rowsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < colsCnt; j++) {
					ok = ok && game[i][j];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < rowsCnt - 1; i++) {
				if (game[i][0]) {
					for (int j = 1; j < colsCnt - 1; j++) {
						if (game[i][j]) {
							ans += howManyConnections(i, j, RIGHT_SIDE);
							ans -= isHorizontallyFree(i, 0, colsCnt - 1);
						} else {
							break;
						}
					}
					ans += isHorizontallyFree(i, 0, colsCnt - 1);
				}
			}
		}

		// opposing top
		if (rowsCnt <= 2) {
			for (int i = 1; i < colsCnt - 1; i++) {
				boolean ok = true;
				for (int j = 0; j < rowsCnt; j++) {
					ok = ok && game[j][i];
				}
				ans += ok ? 1 : 0;
			}
		} else {
			for (int i = 1; i < colsCnt - 1; i++) {
				if (game[0][i]) {
					for (int j = 1; j < rowsCnt - 1; j++) {
						if (game[j][i]) {
							ans += howManyConnections(j, i, BOTTOM_SIDE);
							ans -= isVerticallyFree(i, 0, rowsCnt - 1);
						} else {
							break;
						}
					}
					ans += isVerticallyFree(i, 0, rowsCnt - 1);
				}
			}
		}

		// left to top
		// left to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// right to top
		// right to bottom
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j >= 1; j--) {
					if (game[i][j]) {
						ans += isVerticallyFree(j, i, 0);
						ans += isVerticallyFree(j, i, rowsCnt - 1);
					} else {
						break;
					}
				}
			}
		}

		// left to left
		long ll = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][0]) {
				for (int j = 1; j < colsCnt - 1; j++) {
					if (game[i][j]) {
						ll += howManyConnections(i, j, LEFT_SIDE) - 1;
						if (i + 1 < rowsCnt - 1) {
							ll -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							ll -= isHorizontallyFree(i - 1, 0, j);
						}
						ll -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += ll / 2;

		// top to top
		long tt = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[0][i]) {
				for (int j = 1; j < rowsCnt - 1; j++) {
					if (game[j][i]) {
						tt += howManyConnections(j, i, TOP_SIDE);
						if (i - 1 > 0) {
							tt -= isVerticallyFree(i - 1, 0, j);
						}
						if (i + 1 < colsCnt - 1) {
							tt -= isVerticallyFree(i + 1, 0, j);
						}
						tt -= isVerticallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += tt / 2;

		// right to right
		long rr = 0;
		for (int i = 1; i < rowsCnt - 1; i++) {
			if (game[i][colsCnt - 1]) {
				for (int j = colsCnt - 2; j > 0; j--) {
					if (game[i][j]) {
						rr += howManyConnections(i, j, RIGHT_SIDE) - 1;
						if (i + 1 < rowsCnt - 1) {
							rr -= isHorizontallyFree(i + 1, 0, j);
						}
						if (i - 1 > 0) {
							rr -= isHorizontallyFree(i - 1, 0, j);
						}
						rr -= isHorizontallyFree(i, 0, j);
					} else {
						break;
					}
				}
			}
		}
		ans += rr / 2;

		// bottom to bottom
		long bb = 0;
		for (int i = 1; i < colsCnt - 1; i++) {
			if (game[rowsCnt - 1][i]) {
				for (int j = rowsCnt - 2; j >= 1; j--) {
					if (game[j][i]) {
						bb += howManyConnections(j, i, BOTTOM_SIDE);
						if (i - 1 > 0) {
							bb -= isVerticallyFree(i - 1, colsCnt - 1, j);
						}
						if (i + 1 < colsCnt - 1) {
							bb -= isVerticallyFree(i + 1, colsCnt - 1, j);
						}
						bb -= isVerticallyFree(i, colsCnt - 1, j);
					} else {
						break;
					}
				}
			}
		}
		ans += bb / 2;

		System.out.println(ans);
	}

	private static void precompute() {
		blockedRows = new int[rowsCnt][];
		blockedCols = new int[colsCnt][];

		for (int i = 0; i < game.length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game[0].length; j++) {
				if (!game[i][j]) {
					m.add(j);
				}
			}
			blockedRows[i] = new int[m.size()];
			for (int j = 0; j < blockedRows[i].length; j++) {
				blockedRows[i][j] = m.get(j);
			}
		}

		for (int i = 0; i < game[0].length; i++) {
			List<Integer> m = new ArrayList<Integer>();
			for (int j = 0; j < game.length; j++) {
				if (!game[j][i]) {
					m.add(j);
				}
			}
			blockedCols[i] = new int[m.size()];
			for (int j = 0; j < blockedCols[i].length; j++) {
				blockedCols[i][j] = m.get(j);
			}
		}

		contiguousFree = new int[4][2000][2000];

		// left
		for (int i = 0; i < colsCnt; i++) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == 0 || contiguousFree[LEFT_SIDE][j][i - 1] >= 1)) {
					contiguousFree[3][j][i] = 1;
				}
			}
		}

		// right
		for (int i = colsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < rowsCnt - 1; j++) {
				if (game[j][i] && (i == colsCnt - 1 || contiguousFree[RIGHT_SIDE][j][i + 1] >= 1)) {
					contiguousFree[RIGHT_SIDE][j][i] = 1;

				}
			}
		}

		// top
		for (int i = 0; i < rowsCnt; i++) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == 0 || contiguousFree[TOP_SIDE][i - 1][j] > 0)) {
					contiguousFree[TOP_SIDE][i][j] = 1;
				}
			}
		}

		// bottom
		for (int i = rowsCnt - 1; i >= 0; i--) {
			for (int j = 1; j < colsCnt - 1; j++) {
				if (game[i][j] && (i == rowsCnt - 1 || contiguousFree[BOTTOM_SIDE][i + 1][j] > 0)) {
					contiguousFree[BOTTOM_SIDE][i][j] = 1;
				}
			}
		}
	}

	static int isVerticallyFree(int c, int r1, int r2) {
		if (r1 > r2) {
			return isVerticallyFree(c, r2, r1);
		}

		int pos = Arrays.binarySearch(blockedCols[c], r1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedCols[c].length) {
			return 1;
		}

		if (blockedCols[c][pos] > r2) {
			return 1;
		}

		return 0;
	}

	static int isHorizontallyFree(int r, int c1, int c2) {
		if (c1 > c2) {
			return isHorizontallyFree(r, c2, c1);
		}

		int pos = Arrays.binarySearch(blockedRows[r], c1);
		if (pos >= 0) {
			return 0;
		}

		pos = -(pos + 1);
		if (pos == blockedRows[r].length) {
			return 1;
		}

		if (blockedRows[r][pos] > c2) {
			return 1;
		}

		return 0;
	}

	static int howManyConnections(int r, int c, int side) {
		int ans = 0;
		if (side == LEFT_SIDE || side == RIGHT_SIDE) {
			for (int i = r + 1; i < rowsCnt; i++) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
			for (int i = r; i >= 0; i--) {
				if (!game[i][c])
					break;
				ans += contiguousFree[side][i][c];
			}
		} else {
			for (int i = c + 1; i < colsCnt; i++) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
			for (int i = c; i >= 0; i--) {
				if (!game[r][i])
					break;
				ans += contiguousFree[side][r][i];
			}
		}

		return ans;
	}

	static void parseGame(String[] g) {
		game = new boolean[rowsCnt][];
		for (int i = 0; i < g.length; i++) {
			game[i] = new boolean[colsCnt];
			for (int j = 0; j < g[0].length(); j++) {
				game[i][j] = g[i].charAt(j) == '.';
			}
		}
	}
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 2003
using namespace std;
bool mp[maxn][maxn];
int n,m;
int s[maxn][maxn];
void build()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+mp[i][j];
}
inline int get(int x1,int y1,int x2,int y2)
{
    return s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
}
int sol0()
{
    int ret=0;
    for(int i=2;i<n;i++)
        ret+=(get(i,1,i,m)==0);
    for(int j=2;j<m;j++)
        ret+=(get(1,j,n,j)==0);
    return ret;
}
int sol1()
{
    int ret=0;
    for(int i=2;i<n;i++)
        for(int j=2;j<m;j++)
        {
            ret+=(get(1,j,i,j)+get(i,1,i,j)==0);
            ret+=(get(1,j,i,j)+get(i,j,i,m)==0);
            ret+=(get(i,j,n,j)+get(i,1,i,j)==0);
            ret+=(get(i,j,n,j)+get(i,j,i,m)==0);
        }
    return ret;
}
int sol2()
{
    int ret=0;
    static int sum[maxn];
    for(int i=2;i<n;i++)
    {
        sum[0]=sum[1]=0;
        for(int j=2;j<m;j++)
        {
            if(mp[i][j])
                sum[j]=0;
            else
            {
                sum[j]=sum[j-1];
                if(get(1,j,i,j)==0)
                    sum[j]++;
                if(get(i,j,n,j)==0)
                    sum[j]++;
            }
        }
        for(int j=2;j<m;j++)
        {
            if(get(1,j,i,j)==0)
            {
                if(!mp[i][j-1])
                    ret+=sum[j-2];
                if(j>2)
                    ret+=(get(i,j-1,n,j-1)==0);
            }
            if(get(i,j,n,j)==0)
            {
                if(!mp[i][j-1])
                    ret+=sum[j-2];
                if(j>2)
                    ret+=(get(1,j-1,i,j-1)==0);
            }
        }
    }
    return ret;
}
void sol()
{
    int ans=sol0()+sol1()+sol2();
    static bool tmp[maxn][maxn];
    memcpy(tmp,mp,sizeof(tmp));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            mp[j][i]=tmp[i][j];
    swap(n,m);
    build();
    ans+=sol2();
    printf("%d\n",ans);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            static char in[maxn];
            scanf("%s",in);
            for(int j=1;j<=m;j++)
                mp[i][j]=(in[j-1]=='#');
        }
        build();
        sol();
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 2003
#define ll long long
using namespace std;
bool mp[maxn][maxn];
int n,m;
int s[maxn][maxn];
void build()
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+mp[i][j];
}
inline int get(int x1,int y1,int x2,int y2)
{
    return s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1];
}
ll sol0()
{
    ll ret=0;
    for(int i=2;i<n;i++)
        ret+=(get(i,1,i,m)==0);
    for(int j=2;j<m;j++)
        ret+=(get(1,j,n,j)==0);
    return ret;
}
ll sol1()
{
    ll ret=0;
    for(int i=2;i<n;i++)
        for(int j=2;j<m;j++)
        {
            ret+=(get(1,j,i,j)+get(i,1,i,j)==0);
            ret+=(get(1,j,i,j)+get(i,j,i,m)==0);
            ret+=(get(i,j,n,j)+get(i,1,i,j)==0);
            ret+=(get(i,j,n,j)+get(i,j,i,m)==0);
        }
    return ret;
}
ll sol2()
{
    ll ret=0;
    static int sum[maxn];
    for(int i=2;i<n;i++)
    {
        sum[0]=sum[1]=0;
        for(int j=2;j<m;j++)
        {
            if(mp[i][j])
                sum[j]=0;
            else
            {
                sum[j]=sum[j-1];
                if(get(1,j,i,j)==0)
                    sum[j]++;
                if(get(i,j,n,j)==0)
                    sum[j]++;
            }
        }
        for(int j=2;j<m;j++)
        {
            if(get(1,j,i,j)==0)
            {
                if(!mp[i][j-1])
                    ret+=sum[j-2];
                if(j>2)
                    ret+=(get(i,j-1,n,j-1)==0);
            }
            if(get(i,j,n,j)==0)
            {
                if(!mp[i][j-1])
                    ret+=sum[j-2];
                if(j>2)
                    ret+=(get(1,j-1,i,j-1)==0);
            }
        }
    }
    return ret;
}
void sol()
{
    ll ans=sol0()+sol1()+sol2();
    static bool tmp[maxn][maxn];
    memcpy(tmp,mp,sizeof(tmp));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            mp[j][i]=tmp[i][j];
    swap(n,m);
    build();
    ans+=sol2();
    printf("%lld\n",ans);
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            static char in[maxn];
            scanf("%s",in);
            for(int j=1;j<=m;j++)
                mp[i][j]=(in[j-1]=='#');
        }
        build();
        sol();
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long       LL;
typedef pair<int, int>  PII;
typedef vector<int>     VI;
typedef vector<LL>      VL;
typedef vector<string>  VS;
typedef vector<PII>     VPII;
#define MM(a,x)  memset(a,x,sizeof(a));
#define ALL(x)   (x).begin(), (x).end()
#define P(x)	   cerr<<"{"#x<<" = "<<(x)<<"}"<<endl;
#define P2(x,y)	   cerr<<"{"#x" = "<<(x)<<", "#y" = "<<(y)<<"}"<<endl;
#define P3(x,y,z)  cerr<<"{"#x" = "<<(x)<<", "#y" = "<<(y)<<", "#z" = "<<(z)<<"}"<<endl;
#define P4(x,y,z,w)cerr<<"{"#x" = "<<(x)<<", "#y" = "<<(y)<<", "#z" = "<<(z)<<", "#w" = "<<(w)<<"}"<<endl;
#define PP(x,i)	 cerr<<"{"#x"["<<i<<"] = "<<x[i]<<"}"<<endl;
#define TM(a,b)	 cerr<<"{"#a" -> "#b": "<<1000*(b-a)/CLOCKS_PER_SEC<<"ms}\n";
#define UN(v)    sort(ALL(v)), v.resize(unique(ALL(v))-v.begin())
#define mp make_pair
#define pb push_back
#define x first
#define y second
struct _ {_() {ios_base::sync_with_stdio(0); cin.tie(0);} stringstream ss;} _;
template<class A, class B> ostream& operator<<(ostream &o, pair<A, B> t) {o << "(" << t.x << ", " << t.y << ")"; return o;}
template<class T> inline string tostring(T x) {_.ss.clear(); _.ss.str(""); _.ss << x; return _.ss.str();}
template<class T> inline T convert(const string& s) {char *p; if(is_integral<T>()) return strtoll(s.c_str(), &p, 10); else return strtod(s.c_str(), &p);}
template<class T> void PV(T a, T b, int p = 0, int w = 0, string s = " ") {int c = 0; while(a != b) {cout << setw(w) << *a++; cout << ((a != b && (!p || ++c % p)) ? s : "\n");} cout.flush();}
template<class T> inline bool chmin(T &a, T b) {return a > b ? a = b, 1 : 0;}
template<class T> inline bool chmax(T &a, T b) {return a < b ? a = b, 1 : 0;}
const LL linf = 0x3f3f3f3f3f3f3f3fLL;
const int inf = 0x3f3f3f3f;
const int mod = int(1e9) + 7;
const int N = 2020;

int n, m;
bool v[N][N];

int sum[N][N];

LL solve() {
	LL res = 0;
	int up[N] = {};
	int down[N] = {};
	int cup[N] = {};
	int cdown[N] = {};
	for(int i = 1; i + 1 < n; i++) {
		for(int j = 0; j < m; j++) {
			int A = sum[i + 1][j + 1] - sum[i + 1][j];
			int B = sum[n][j + 1] - sum[n][j] - A + 1;
			up[j] = (A == i + 1);
			down[j] = (B == n - i);
			cup[j + 1] = cup[j] + up[j];
			cdown[j + 1] = cdown[j] + down[j];
		}
		for(int j = 1; j + 1 < m; j++) {
			if(!v[i][j]) continue;
			int k = j;
			while(k + 1 < m && v[i][k]) k++;
			int nup = cup[k] - cup[j];
			int ndn = cdown[k] - cdown[j];
			res += nup * ndn;

			// [j, k)
			for(int x = j; x + 2 < k; x++) {
				if(up[x]) res += cup[k] - cup[x + 2];
				if(down[x]) res += cdown[k] - cdown[x + 2];
			}
			j = k - 1;
		}
	}
	return res;
}

int main() {
	cin >> n >> m;
	for(int i = 0; i < n; i++) {
		string s;
		cin >> s;
		for(int j = 0; j < m; j++) {
			v[i][j] = (s[j] == '.');
			sum[i + 1][j + 1] = sum[i][j + 1] + sum[i + 1][j] - sum[i][j] + v[i][j];
		}
	}

	LL res = 0;
	LL cntx = 0, cnty = 0;
	for(int i = 1; i + 1 < n; i++) if(sum[i + 1][m] - sum[i][m] == m) cntx++;
	for(int i = 1; i + 1 < m; i++) if(sum[n][i + 1] - sum[n][i] == n) cnty++;

	for(int i = 1; i + 1 < n; i++)
		for(int j = 1; j + 1 < m; j++) {
			if(!v[i][j]) continue;
			int up = sum[i + 1][j + 1] - sum[i + 1][j];
			int down = sum[n][j + 1] - sum[n][j] - up + 1;

			int left = sum[i + 1][j + 1] - sum[i][j + 1];
			int right = sum[i + 1][m] - sum[i][m] - left + 1;

			up = (up == i + 1);
			down = (down == n - i);
			left = (left == j + 1);
			right = (right == m - j);

			if(up && left) res++;
			if(up && right) res++;
			if(down && left) res++;
			if(down && right) res++;
		}

	res += solve();
	for(int i = 0; i < N; i++)
		for(int j = i; j < N; j++)
			swap(v[i][j], v[j][i]);
	swap(n, m);

	MM(sum, 0);
	for(int i = 0; i < n; i++)
		for(int j = 0; j < m; j++)
			sum[i + 1][j + 1] = sum[i][j + 1] + sum[i + 1][j] - sum[i][j] + v[i][j];

	res += solve();
	res -= (n - 3) * cntx;
	res -= (m - 3) * cnty;
	cout << res << endl;
	return 0;
}


#include<bits/stdc++.h>
#define LL long long
using namespace std;

int n,m;
char w[2005][2005];

int subsetLR[2005] = {0},subsetRL[2005] = {0},subsetTB[2005] = {0},subsetBT[2005] = {0};
int lengthLR[2005][2005]={0} , lengthRL[2005][2005]={0},lengthTB[2005][2005]={0},lengthBT[2005][2005]={0};
int bitLR[2005][2005] = {0}, bitRL[2005][2005] = {0},bitTB[2005][2005] = {0},bitBT[2005][2005] = {0};
LL ans0 = 0, ans1 = 0, ans2 = 0;

void fillSubset(){
    for(int i=0; i<n;i++){
        int cnt = 0;
        for(int j=0; j<m;j++){
            if(w[i][j] == '.') cnt++;
            else break;
        }
        subsetLR[i] = cnt;
        cnt = 0;
        for(int j=m-1; j>=0; j--){
            if(w[i][j] == '.') cnt++;
            else break;
        }
        subsetRL[i] = cnt;
    }

    for(int j=0; j<m;j++){
        int cnt = 0;
        for(int i=0; i<n;i++){
            if(w[i][j] == '.') cnt++;
            else break;
        }
        subsetTB[j] = cnt;
        cnt = 0;
        for(int i=n-1; i>=0; i--){
            if(w[i][j] == '.') cnt++;
            else break;
        }
        subsetBT[j] = cnt;
    }
}

void fillLength(){
    for(int i=0; i<n; i++){
        int cnt = 0;
        for(int j=0; j<m;j++){
            if(w[i][j] == '.') cnt++;
            else cnt = 0;
            lengthLR[i][j] = cnt;
        }
        cnt = 0;
        for(int j=m-1; j>=0; j--){
            if(w[i][j] == '.') cnt++;
            else cnt = 0;
            lengthRL[i][j] = cnt;

        }
    }

    for(int j=0; j<m;j++){
        int cnt = 0;
        for(int i=0; i<n;i++){
            if(w[i][j] == '.') cnt++;
            else cnt = 0;
            lengthTB[i][j] = cnt;
        }
        cnt = 0;
        for(int i=n-1; i>=0; i--){
            if(w[i][j] == '.') cnt++;
            else cnt = 0;
            lengthBT[i][j] = cnt;
        }
    }
}

void fillBIT(){
    for(int i=0; i<n;i++){
        int v = subsetLR[i];
        for(int j=v; j;j--){
            for(int k=i+1; k<2005;k+=(k&-k)){
                bitLR[k][j]++;
            }
        }

        v = subsetRL[i];
        for(int j=v; j;j--){
            for(int k=i+1; k<2005;k+=(k&-k)){
                bitRL[k][j]++;
            }
        }
    }

    for(int j=0; j<m;j++){
        int v = subsetTB[j];
        for(int i=v; i;i--){
            for(int k=j+1; k<2005;k+=(k&-k)){
                bitTB[k][i]++;
            }
        }

        v = subsetBT[j];
        for(int i=v; i;i--){
            for(int k=j+1; k<2005;k+=(k&-k)){
                bitBT[k][i]++;
            }
        }
    }
}

int sum(int x,int v, int t){
    int ret = 0;
    for(int i=x; i; i-= (i&-i)){
        if(t==0) ret += bitLR[i][v];
        if(t==1) ret += bitRL[i][v];
        if(t==2) ret += bitTB[i][v];
        if(t==3) ret += bitBT[i][v];
    }
    return ret;
}

int query(int x, int y, int v, int t){
    if(x < 0 || y < 0) return 0;
    if(x == 0) x++;
    if(x > y) return 0;
    return sum(y+1,v,t) - sum(x, v, t);
}

void precompute(){
    fillSubset();
    fillLength();
    fillBIT();
}

void fillAns0(){
    for(int i=1; i<n-1; i++){
        bool ok = true;
        for(int j=0; j<m;j++) ok &= w[i][j] == '.';
        ans0 += ok;
    }

    for(int j=1; j<m-1;j++){
        bool ok = true;
        for(int i=0; i<n;i++) ok &= w[i][j] == '.';
        ans0 += ok;
    }
}

void fillAns1(){
    for(int i=1; i<n-1; i++){
        for(int j=1; j<m-1;j++){
            ans1 += (subsetLR[i] >= j+1 && subsetTB[j] >= i+1);
            ans1 += (subsetRL[i] >= m-j && subsetTB[j] >= i+1);
            ans1 += (subsetLR[i] >= j+1 && subsetBT[j] >= n-i);
            ans1 += (subsetRL[i] >= m-j && subsetBT[j] >= n-i);
        }
    }
}

void fillAns2(){
    for(int i=1; i<n-1;i++){
        for(int j=1; j<m-1;j++){
            if(subsetLR[i] >= j+1){
                ans2 += query(i-lengthTB[i][j]+1, i-2, j+1, 0);
                ans2 += query(i-lengthTB[i][j]+1, i-1, m-j, 1);
            }
            if(subsetRL[i] >= m-j){
                ans2 += query(i-lengthTB[i][j]+1, i-2, m-j, 1);
                ans2 += query(i-lengthTB[i][j]+1, i-1, j+1, 0);
            }
        }
    }
    for(int j=1; j<m-1; j++){
        for(int i=1; i<n-1;i++){
            if(subsetTB[j] >= i+1){
                ans2 += query(j-lengthLR[i][j]+1, j-2, i+1, 2);
                ans2 += query(j-lengthLR[i][j]+1, j-1, n-i, 3);
            }
            if(subsetBT[j] >= n-i){
                ans2 += query(j-lengthLR[i][j]+1, j-2, n-i, 3);
                ans2 += query(j-lengthLR[i][j]+1, j-1, i+1, 2);
            }
        }
    }
}

int main(){
    scanf("%d%d", &n,&m);
    for(int i=0; i<n;i++)scanf("%s", w[i]);

    precompute();

//    printf("%I64d %I64d %I64d\n", ans0, ans1, ans2);
    fillAns0();
//    printf("%I64d %I64d %I64d\n", ans0, ans1, ans2);
    fillAns1();
//    printf("%I64d %I64d %I64d\n", ans0, ans1, ans2);
    fillAns2();
//    printf("%I64d %I64d %I64d\n", ans0, ans1, ans2);
    printf("%I64d\n", ans0 + ans1 + ans2);
    return 0;
}