#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
#include <cassert>
using namespace std;
typedef long long ll;
#define ss second
#define ff first
#define all(X) X.begin(), X.end()
#define rall(X) X.rbegin(), X.rend()
#define cinall(X) for(auto &i:X)cin >> i
#define printall(X) for(auto &i:X)cout << i
#define printFromTo(cont, i, j, ch) for(int _ = i; _ <= j; _++)cout << cont[_] << ch
#define readFromTo(cont, i, j) for(int _ = i; _ <= j; _++)cin >> cont[_]
#define fillFromTo(cont, i, j, x) for(int _ = i; _ <= j; _++)cont[_] = x;
#define pb push_back
#define MAKE_UNIQUE_KEEP_ORDER(vec) do { \
	unordered_set<decltype((vec).front())> seen; \
	(vec).erase(remove_if((vec).begin(), (vec).end(), [&](auto &val) { \
		if (seen.count(val)) return true; \
		seen.insert(val); \
		return false; \
	}), (vec).end()); \
} while(0)
#define UNIQUE_SORT(vec) do { \
	sort((vec).begin(), (vec).end()); \
	(vec).erase(unique((vec).begin(), (vec).end()), (vec).end()); \
} while(0)
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
#define MIN(v) *min_element(all(v))
#define MAX(v) *max_element(all(v))
#define LB(c, x) (lower_bound((c).begin(), (c).end(), (x)) - (c).begin())
#define UB(c, x) (upper_bound((c).begin(), (c).end(), (x)) - (c).begin())
const int N = 2e3 + 5;
const int LOG = 30;
const long long INFLL = 1e18;
const int INF = 1e9;
const long double epsilon = 0.000001;
const long long mod = 1e9 + 7;
constexpr ll TEN[] = {
	1LL,
	10LL,
	100LL,
	1000LL,
	10000LL,
	100000LL,
	1000000LL,
	10000000LL,
	100000000LL,
	1000000000LL,
	10000000000LL,
	100000000000LL,
	1000000000000LL,
	10000000000000LL,
	100000000000000LL,
	1000000000000000LL,
	10000000000000000LL,
	100000000000000000LL,
	1000000000000000000LL,
};
long long binPowByMod(long long x, long long power, long long modx) {
	long long res = 1;
	long long base = x % modx;
	while (power > 0) {
		if (power & 1) res = (res * base) % modx;
		base = (base * base) % modx;
		power >>= 1;
	}
	return res;
}
void set_IO(string str = "")
{
	if (!str.empty()) {
		freopen((str + ".in").c_str(), "r", stdin);
		freopen((str + ".out").c_str(), "w", stdout);
	}
}
int a[N][N];
int down[N][N];
void solve()
{
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			char ch;
			cin >> ch;
			if (ch == '.')
				a[i][j] = 0;
			else
				a[i][j] = 1;
		}
	}
	for (int i = 1; i <= m; i++)
	{
		down[n + 1][i] = 0;
	}
	for (int i = n; i >= 1; i--)
	{
		for (int j = 1; j <= m; j++)
		{
			if (a[i][j] == 1)
				down[i][j] = 0;
			else
				down[i][j] = down[i + 1][j] + 1;
		}
	}
	long long ans = 0;
	for (int i = 1; i <= n; i++)
	{
		vector<int>left(m + 1, 0);
		vector<int>right(m + 1, m + 1);
		stack<pair<int, int>>st;
		for (int j = 1; j <= m; j++)
		{
			while (!st.empty() && down[i][j] < st.top().first)
			{
				right[st.top().second] = j;
				st.pop();
			}
			if (!st.empty())
			{
				left[j] = st.top().second;
			}
			st.push({ down[i][j], j });
		}
		for (int j = 1; j <= m; j++)
		{
			if (a[i][j] == 1)continue;
			long long l_cnt = j - left[j];
			long long r_cnt = right[j] - j;
			long long x = 0;
			x += 1ll * l_cnt * r_cnt;
			x += 1ll * l_cnt * (((r_cnt - 1) * r_cnt) / 2);
			x += 1ll * r_cnt * (((l_cnt - 1) * l_cnt) / 2);
			ans += (1ll * x * ((1ll * down[i][j] * (down[i][j] + 1)) / 2ll));
		}
	}
	cout << ans << endl;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t = 1;
	//cin >> t;
	while (t--) {
		solve();
		cout << endl;
	}
	return 0;
}
Compilation message (stderr)
strah.cpp: In function 'void set_IO(std::string)':
strah.cpp:87:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   87 |                 freopen((str + ".in").c_str(), "r", stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
strah.cpp:88:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
   88 |                 freopen((str + ".out").c_str(), "w", stdout);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict | Execution time | Memory | Grader output | 
|---|
| Fetching results... |