This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/golded3/geutil.cpp

789 lines
18 KiB
C++
Raw Normal View History

2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
// GoldED+
// Copyright (C) 1990-1999 Odinn Sorensen
// Copyright (C) 1999-2000 Alexander S. Aganichev
// ------------------------------------------------------------------
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston,
// MA 02111-1307 USA
// ------------------------------------------------------------------
// $Id$
// ------------------------------------------------------------------
// Global utility functions (not overlayed in 16-bit DOS).
// ------------------------------------------------------------------
#include <cstdarg>
#include <golded.h>
#define UPDATE_STATUSLINE_ERROR " ERROR! Please look a log file and make a report to developers! "
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
extern bool in_arealist;
extern GPickArealist* PickArealist;
// ------------------------------------------------------------------
void update_statuslines() {
char buf[200]; /* FIXME: it is need to use dynamic arrays in this fuction to prevent buffer overflow or screen garbage */
char * const buf_end = buf+199;
2000-02-25 11:04:07 +00:00
static char old_status_line[200] = "";
char * const old_status_line_end = old_status_line+199;
2000-02-25 11:04:07 +00:00
static int called = NO;
const int WIDE= sizeof(buf)>MAXCOL? MAXCOL : sizeof(buf)-1;
2000-02-25 11:04:07 +00:00
HandleGEvent(EVTT_REMOVEVOCBUF);
if(CFG->switches.get(dispstatusline) or not called) // FIXME: Strange, status line displayed always in first call. May be need to change?
{
2000-02-25 11:04:07 +00:00
called = YES;
vchar sep = _box_table(W_BSTAT, 3);
2001-01-28 15:13:00 +00:00
char help[200], clkinfo[200];
2000-02-25 11:04:07 +00:00
*clkinfo = NUL;
*help = NUL;
if(CFG->switches.get(statuslineclock))
{
2005-10-20 21:10:42 +00:00
time32_t t = gtime(NULL);
struct tm tm; glocaltime(&tm, &t);
if( strftimei(help, 40, LNG->StatusLineTimeFmt, &tm) )
gsprintf(PRINTF_DECLARE_BUFFER(clkinfo), " %s", help);
2000-02-25 11:04:07 +00:00
}
if(CFG->statuslinehelp == -1)
*help = NUL;
else if(CFG->statuslinehelp)
gsprintf(PRINTF_DECLARE_BUFFER(help), "%s ", LNG->StatusLineHelp);
2000-02-25 11:04:07 +00:00
else
gsprintf(PRINTF_DECLARE_BUFFER(help), "%s%s%s%s %s%i.%i.%i%s ",
2000-02-25 11:04:07 +00:00
__gver_prename__,
__gver_name__,
__gver_postname__,
__gver_platform__,
__gver_preversion__,
__gver_major__,
__gver_minor__,
__gver_release__,
__gver_postversion__
2000-02-25 11:04:07 +00:00
);
2001-01-28 15:13:00 +00:00
int help_len = strlen(help);
int clk_len = strlen(clkinfo);
int len = WIDE-help_len-clk_len-2;
// LOG.printf("! --- %i bytes help=\"%s\"", help_len, help?help:"NULL");
// LOG.printf("! --- %i bytes information=\"%s\"", len, information?information:"NULL");
// LOG.printf("! --- %i bytes clkinfo=\"%s\"", clk_len, clkinfo?clkinfo:"NULL");
gsprintf(PRINTF_DECLARE_BUFFER(buf), "%c%s%-*.*s%s ", goldmark, help, len, len, information, clkinfo);
2001-01-28 15:13:00 +00:00
char *begin = buf;
char *obegin = old_status_line;
char *end = buf + WIDE;
char *oend = old_status_line + WIDE;
while((*begin != NUL) and (*begin == *obegin) and (begin<buf_end) and (obegin<old_status_line_end)) {
2001-01-28 15:13:00 +00:00
++begin;
++obegin;
}
if(begin == end)
2000-02-25 11:04:07 +00:00
return;
2001-01-28 15:13:00 +00:00
// we have at least one mismatch
if(*obegin) {
while((*end == *oend) and (buf<end) and (old_status_line<oend) ) {
2001-01-28 15:13:00 +00:00
--end;
--oend;
}
}
len = end-begin+1;
memcpy( obegin, begin, (len<sizeof(old_status_line))? len : sizeof(old_status_line) );
2000-02-25 11:04:07 +00:00
#ifdef GOLD_MOUSE
gmou.GetStatus();
if(gmou.Row() == MAXROW-1)
gmou.HideCursor();
#endif
int row, col;
vposget(&row, &col);
2001-01-28 15:13:00 +00:00
*(++end) = NUL;
wwprintstr(W_STAT, 0,begin-buf, C_STATW, begin);
if(*help and ((begin - buf) < (help_len-1)) and ((end - buf) > (help_len-1)))
wwprintc(W_STAT, 0,help_len-1, C_STATW, sep);
if(((begin - buf) < (WIDE-clk_len)) and ((end - buf) > (WIDE-clk_len)))
wwprintc(W_STAT, 0,WIDE-clk_len, C_STATW, sep);
2000-02-25 11:04:07 +00:00
vposset(row, col);
#ifdef GOLD_MOUSE
if(gmou.Row() == MAXROW-1)
gmou.ShowCursor();
#endif
}
} /* update_statuslines() */
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
void update_statusline(const char* info) {
if ( !(info) )
{
LOG.errpointer(__FILE__, __LINE__);
LOG.printf( "! Parameter is NULL pointer: update_statusline(NULL).");
strxcpy(information, UPDATE_STATUSLINE_ERROR, sizeof(information));
}
else
{
strxcpy(information, info, sizeof(information));
}
2000-02-25 11:04:07 +00:00
update_statuslines();
}
// ------------------------------------------------------------------
void update_statuslinef(const char *format, const char *token, ...)
{
if ( !(format && *format && token && *token) )
{
LOG.errpointer(__FILE__, __LINE__);
LOG.printf( "! Parameter is NULL pointer or empty string: update_statuslinef(\"%s\",\"%s\",...).",
(format?(*format)?format:"":"(NULL)"), (token?(*token)?token:"":"(NULL)") );
update_statusline(UPDATE_STATUSLINE_ERROR);
return;
}
bool error = false;
2000-11-27 06:15:29 +00:00
char winfobuf[350];
2000-02-25 11:04:07 +00:00
va_list argptr;
va_start(argptr, token);
try
{
vsprintf(winfobuf, format, argptr);
}
catch(...)
{
if (*token)
sprintf(winfobuf, "ERROR: Update %s in your GOLDLANG.CFG or report to author.", token);
else
sprintf(winfobuf, "ERROR: \"%s\". Report to author.", format);
error = true;
}
2000-02-25 11:04:07 +00:00
va_end(argptr);
2000-11-27 06:15:29 +00:00
update_statusline(winfobuf);
if (error)
{
SayBibi();
waitkeyt(1000);
}
2000-02-25 11:04:07 +00:00
}
// ------------------------------------------------------------------
void w_shadow() {
if(CFG->switches.get(screenshadows))
wshadow(C_SHADOW);
}
// ------------------------------------------------------------------
void w_info(const char* info) {
static int wh=-1;
static int srow;
static int scol;
static int erow;
static int ecol;
static int len;
static char buf[150] = { "" };
char* buf2 = NULL;
int prev_wh = whandle();
if(wh != -1)
wactiv_(wh);
if(info) {
int tmp = strlen(info);
if(tmp > MAXCOL-5) {
buf2 = (char *)throw_malloc(MAXCOL-5);
strxcpy(buf2, info, MAXCOL-5);
info = buf2;
tmp = MAXCOL-6;
}
if(wh == -1) {
len = tmp;
srow = inforow;
erow = srow+3-1;
scol = ((MAXCOL-len)/2)-1;
ecol = scol+len+1;
wh = wopen(srow, scol, erow, ecol, W_BINFO, C_INFOB, C_INFOW);
w_shadow();
}
else {
if(len != tmp) {
len = tmp;
scol = ((MAXCOL-len)/2)-1;
ecol = scol+len+1;
wclose();
wh = wopen(srow, scol, erow, ecol, W_BINFO, C_INFOB, C_INFOW);
w_shadow();
}
}
if(not streql(buf, info)) {
strcpy(buf, info);
wprints(0, 0, C_INFOW, buf);
}
}
else {
if(wh != -1) {
*buf = NUL;
wclose();
wh = -1;
}
}
wactiv_(prev_wh);
if(buf2)
throw_free(buf2);
}
// ------------------------------------------------------------------
void w_infof(const char* format, ...) {
char winfobuf[350];
va_list argptr;
va_start(argptr, format);
vsprintf(winfobuf, format, argptr);
va_end(argptr);
w_info(winfobuf);
}
// ------------------------------------------------------------------
void w_progress(int mode, vattr attr, long pos, long size, const char* title) {
2000-02-25 11:04:07 +00:00
static int wh = -1;
2001-02-01 11:29:10 +00:00
static long prev_pos = 0;
2000-02-25 11:04:07 +00:00
int prev_wh = whandle();
if(wh != -1)
wactiv_(wh);
switch(mode) {
case MODE_NEW:
oops:
if(wh == -1) {
wh = wopen_(inforow, ((MAXCOL-63)/2)-1, 3, 63, W_BINFO, C_INFOB, C_INFOW);
set_title(title, TCENTER, C_INFOT);
title_shadow();
2001-02-01 11:29:10 +00:00
goto force_update;
2000-02-25 11:04:07 +00:00
}
case MODE_UPDATE:
if(wh == -1)
goto oops; // Oops, someone forgot to open the window..
2001-02-01 11:29:10 +00:00
if((pos*58/size) != (prev_pos*58/size)) {
force_update:
2001-03-17 21:17:57 +00:00
wpropbar(1, 0, 59, attr, pos, size);
2001-02-01 11:29:10 +00:00
}
prev_pos = pos;
2000-02-25 11:04:07 +00:00
break;
case MODE_QUIT:
if(wh != -1) {
wclose();
wunlink(wh);
wh = -1;
2001-02-01 11:29:10 +00:00
prev_pos = 0;
2000-02-25 11:04:07 +00:00
}
break;
}
wactiv_(prev_wh);
}
// ------------------------------------------------------------------
void maketitle() {
wtitle(m_title, m_titlepos, m_titleattr);
}
2002-11-09 21:08:34 +00:00
// ------------------------------------------------------------------
int maketitle_and_status(char *dir) {
maketitle();
update_statuslinef(LNG->ImportStatus, "ST_IMPORTSTATUS", dir);
2002-11-09 21:32:10 +00:00
return 0;
2002-11-09 21:08:34 +00:00
}
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
void set_title(const char* t, int p, vattr a) {
2000-02-25 11:04:07 +00:00
strcpy(m_title, t);
m_titlepos = p;
m_titleattr = a;
}
// ------------------------------------------------------------------
void title_shadow() {
maketitle();
w_shadow();
}
// ------------------------------------------------------------------
int IsQuoteChar(const char* s) {
if(*s) {
if(*s == '>')
return true;
if(*AA->Quotechars())
if(strchr(AA->Quotechars(), *s))
return true;
}
return false;
}
// ------------------------------------------------------------------
int is_quote(const char* ptr) {
const char* endptr = ptr + 11;
// Skip leading whitespace
while((*ptr == ' ') or (*ptr == LF) or issoftcr(*ptr))
ptr++;
// Check for empty string
if((*ptr == NUL) or (ptr >= endptr))
return false;
// Check for userdefined quotechars after first whitespace
2005-10-28 03:14:32 +00:00
if(IsQuoteChar(ptr))
2000-02-25 11:04:07 +00:00
return true;
2001-07-03 04:27:54 +00:00
endptr = ptr + 11; // match 10 chars after whitespaces
2005-10-28 03:14:32 +00:00
while (*ptr && !IsQuoteChar(ptr) &&
!iscntrl(*ptr) &&
!strchr(AA->Quotestops(), *ptr) &&
!isspace(*ptr)) ptr++;
if ((ptr < endptr) && IsQuoteChar(ptr))
return true;
/*
2000-02-25 11:04:07 +00:00
int spaces = 0;
while((ptr < endptr) and *ptr) {
if(*ptr == LF or issoftcr(*ptr)) {
// Ignore LF's and SOFTCR's and extend check zone if found
endptr++;
}
else if(*ptr == '>') {
// Found true quote char
return true;
}
else if(*ptr == ' ') {
spaces++;
if(spaces > 1)
return false;
}
2000-12-24 19:47:06 +00:00
else if(iscntrl(*ptr) or strchr(AA->Quotestops(), *ptr)) {
2000-02-25 11:04:07 +00:00
// Found a char that cannot occur in a quotestring
return false;
}
ptr++;
}
2005-10-28 03:14:32 +00:00
*/
2000-02-25 11:04:07 +00:00
return false;
}
2005-10-16 03:41:29 +00:00
// ------------------------------------------------------------------
2005-10-27 23:41:58 +00:00
bool is_quote2(Line* line, const char* ptr)
2005-10-16 03:41:29 +00:00
{
if (!CFG->quoteusenewai) return true;
char *head = (char *)ptr;
// search first '>' before CR, NUL or any other quote character
for (bool found = false; !found; ptr++)
{
if (*ptr == '>')
found = true;
else
{
if (IsQuoteChar(ptr) || (*ptr == CR) || !*ptr)
return true;
}
}
// line is double quoted?
if (is_quote(ptr))
return true;
// if "SPACE*[a-zA-Z]{0, 3}>"
for (ptr--; isspace(*head); head++);
int nr = 0;
for (char *tmp = head; tmp < ptr; tmp++)
{
char ch = g_toupper(*tmp);
2005-10-16 03:41:29 +00:00
if ((ch >= 'A') && (ch <= 'Z'))
nr++;
}
if ((nr < 4) && (nr == (ptr-head)))
return true;
// take a look at previous lines
2005-10-27 23:41:58 +00:00
Line *paragraph = NULL;
2005-10-16 03:41:29 +00:00
for (Line *ln = line->prev; ln; ln = ln->prev)
{
// previous line is quoted?
if (ln->isquote())
return true;
// or begin of paragraph?
if ((ln->txt.length() == 0) ||
(ln->txt[0] == LF) ||
(ln->txt[0] == CR))
2005-10-27 23:41:58 +00:00
{
if (paragraph) return true;
else
{
paragraph = ln;
continue;
}
}
2005-10-16 03:41:29 +00:00
// or kludge?
if (ln->txt[0] == CTRL_A)
return true;
// found begin of citation?
const char *begin = strrchr(ln->txt.c_str(), '<');
2005-10-16 03:41:29 +00:00
if (begin)
{
// found both '<' and '>'?
if (strchr(begin, '>'))
return true;
for (Line *ln2 = ln->next; ln2 != line; ln2 = ln2->next)
{
// found both '<' and '>'?
if (strchr(ln2->txt.c_str(), '>'))
return true;
}
2005-10-27 23:41:58 +00:00
// hide false paragraph
if (paragraph) paragraph->type |= GLINE_TXTH;
2005-10-16 03:41:29 +00:00
return false; // don't quote current line
}
}
return true;
}
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
vattr quotecolor(const char* line) {
2000-02-25 11:04:07 +00:00
2001-05-09 20:45:13 +00:00
char buf[MAXQUOTELEN];
2000-02-25 11:04:07 +00:00
uint len;
GetQuotestr(line, buf, &len);
uint qc = 0;
for(uint i=0; i<len; i++)
if(IsQuoteChar(&buf[i]))
qc++;
return (qc & 1) ? C_READQ : C_READQ2;
}
// ------------------------------------------------------------------
int GetQuotestr(const char* ptr, char* qbuf, uint* qlen) {
if(is_quote(ptr)) {
const char* lp = ptr;
int n, x;
2005-10-28 03:14:32 +00:00
/*
2001-05-09 20:45:13 +00:00
for(;;) {
2000-02-25 11:04:07 +00:00
2001-05-09 20:45:13 +00:00
// Skip leading spaces
2000-02-25 11:04:07 +00:00
while(isspace(*lp) or issoftcr(*lp))
lp++;
2001-05-09 20:45:13 +00:00
if(IsQuoteChar(lp)) { // Type 1 : ">xxxx>" and ">xxxx:"
2000-02-25 11:04:07 +00:00
lp++;
2001-05-09 20:45:13 +00:00
while(isspace(*lp) or issoftcr(*lp))
lp++;
if(is_quote(lp))
continue;
if(not (IsQuoteChar(lp-1) or (*(lp-1) == ':'))) {
while(not IsQuoteChar(lp))
lp--;
lp++;
}
2000-02-25 11:04:07 +00:00
}
2001-05-09 20:45:13 +00:00
else { // Type 2: "xxxx>"
while(not (IsQuoteChar(lp) and not IsQuoteChar(lp+1)) and (*lp != CR) and (*lp != NUL))
++lp;
if(is_quote(lp))
continue;
if(*lp)
lp++;
}
break;
2000-02-25 11:04:07 +00:00
}
2005-10-28 03:14:32 +00:00
*/
while (isspace(*lp) or issoftcr(*lp)) lp++;
while (!IsQuoteChar(lp)) lp++;
while (IsQuoteChar(lp)) lp++;
2000-02-25 11:04:07 +00:00
// lp now points to the character after the quotestring
2001-05-09 20:45:13 +00:00
x = lp - ptr;
if((*lp != NUL) and (isspace(*lp) or issoftcr(*lp)))
x++;
2000-02-25 11:04:07 +00:00
for(*qlen = n = 0; (n < x) and ((*qlen) < MAXQUOTELEN-1); n++, ptr++) {
2001-05-09 20:45:13 +00:00
if((*ptr != LF) and not issoftcr(*ptr)) {
*qbuf++ = *ptr;
(*qlen)++;
}
2000-02-25 11:04:07 +00:00
}
2001-05-09 20:45:13 +00:00
*qbuf = NUL;
2000-02-25 11:04:07 +00:00
}
else {
*qbuf = NUL;
*qlen = 0;
}
return *qlen;
}
// ------------------------------------------------------------------
static int KeyCmp(const gkey* a, const gkey* b) {
return CmpV(*a, *b);
}
// ------------------------------------------------------------------
gkey SearchKey(gkey key, std::list<CmdKey>::iterator keys, int totkeys) {
2000-02-25 11:04:07 +00:00
std::list<CmdKey>::iterator kmin;
2000-02-25 11:04:07 +00:00
int again = 0;
do {
kmin = keys;
int tkeys=totkeys;
while(tkeys > 0) {
int j = KeyCmp(&key, &(kmin->key));
if(j == 0)
return(kmin->cmd);
else if(j < 0)
break;
else {
kmin++;
tkeys--;
}
}
// Key not found. Try again, this time without the scancode.
key &= 0x00FF;
} while(not again++ and key);
return 0;
}
// ------------------------------------------------------------------
static void call_func_geutil(VfvCP func) {
struct _menu_t* menu;
int row, col;
bool hidden = vcurhidden();
vposget(&row, &col);
menu = gwin.cmenu;
(*func)();
gwin.cmenu = menu;
vposset(row, col);
if(hidden)
vcurhide();
else
vcurshow();
}
2000-02-25 11:04:07 +00:00
// ------------------------------------------------------------------
void call_help() {
// search through onkey linked list for a
// matching defined onkey. if one is found,
// then save the current environment, call the
// onkey's function, and restore the environment.
KBnd* onkey = gkbd.onkey;
while(onkey != NULL) {
if(onkey->keycode == Key_F1) {
call_func_geutil(onkey->func);
break;
}
onkey = onkey->prev;
}
}
// ------------------------------------------------------------------
2006-07-08 18:50:24 +00:00
void CheckTick(gkey quitkey)
{
if (gkbd.tickvalue < gkbd.tickpress)
2006-07-09 10:27:53 +00:00
gkbd.tickpress = gkbd.tickvalue;
2000-02-25 11:04:07 +00:00
2006-07-09 10:27:53 +00:00
Clock idle_secs = (gkbd.tickvalue - gkbd.tickpress)/10;
2000-02-25 11:04:07 +00:00
2006-07-08 18:50:24 +00:00
if (CFG->timeout)
{
if (idle_secs >= CFG->timeout)
{
2000-02-25 11:04:07 +00:00
kbput(quitkey);
return;
}
}
IdleCheckSemaphores();
if(CFG->screenblanker) {
if(idle_secs >= CFG->screenblanker) {
blanked = true;
ScreenBlankIdle();
kbdsettickfunc(ScreenBlankIdle);
getxch();
blanked = false;
ScreenBlankIdle();
kbdsettickfunc(update_statuslines);
//maybe we've scanned areas while in screenblanker, so
//update screen
if(in_arealist) {
PickArealist->update();
PickArealist->do_delayed();
}
}
}
}
// ------------------------------------------------------------------
2006-07-08 18:50:24 +00:00
void IdleCheckSemaphores()
{
2000-02-25 11:04:07 +00:00
// I don't like this solution either... :(
static Clock last_secs = 0;
2006-07-08 18:50:24 +00:00
if (gkbd.tickvalue < gkbd.tickpress)
2006-07-09 10:27:53 +00:00
gkbd.tickpress = gkbd.tickvalue;
2006-07-08 18:50:24 +00:00
2006-07-09 10:27:53 +00:00
Clock idle_secs = (gkbd.tickvalue - gkbd.tickpress)/10;
2000-02-25 11:04:07 +00:00
// Make sure the stuff below is only run once in a second
if(not idle_secs or (idle_secs - last_secs == 0))
return ;
if(in_arealist) {
if(CFG->semaphore.idletime) {
if((idle_secs % CFG->semaphore.idletime) == 0)
CheckSemaphores();
}
}
last_secs = idle_secs;
}
// ------------------------------------------------------------------
char* strtmp(const char* str) {
static INam tmp;
return strxcpy(tmp, str, sizeof(tmp));
}
// ------------------------------------------------------------------
2003-12-10 08:35:16 +00:00
bool find(const std::vector<const char *> &vec, const char *str) {
std::vector<const char *>::const_iterator i;
for(i = vec.begin(); i != vec.end(); i++)
if(streql(*i, str))
return true;
return false;
}
2007-01-08 12:09:42 +00:00
bool find(const std::vector<std::string> &vec, const std::string &str)
{
std::vector<std::string>::const_iterator it = vec.begin();
std::vector<std::string>::const_iterator end = vec.end();
for (; it != end; it++)
{
if ((*it) == str)
return true;
}
return false;
}