tFix for Win32 high score bug; score file now fflush'ed after writes to be more… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 5f2248351aaab50e701b92db134223fbf74f763b | |
parent fc6e83182ef84919681049077dc6791fd7515a9e | |
Author: Ben Webb <[email protected]> | |
Date: Sun, 13 May 2001 03:24:02 +0000 | |
Fix for Win32 high score bug; score file now fflush'ed after writes to be more | |
crash-tolerant and multi-user friendly; gtk_clists, gtk_texts and gtk_paneds | |
made more usable on Win32. | |
Diffstat: | |
M ChangeLog | 7 ++++++- | |
M src/gtk_client.c | 2 +- | |
M src/gtkport.c | 187 +++++++++++++++++++++++++++--… | |
M src/gtkport.h | 1 + | |
M src/serverside.c | 5 ++++- | |
5 files changed, 178 insertions(+), 24 deletions(-) | |
--- | |
diff --git a/ChangeLog b/ChangeLog | |
t@@ -1,4 +1,9 @@ | |
cvs | |
+ - Fixes for spurious tipoffs | |
+ - High scores should now be written properly on Win32 systems | |
+ - Various minor usability fixes on Win32 systems | |
+ | |
+1.5.0beta2 29-04-2001 | |
- Various fixes for installation on BSD systems and Mac OS X | |
- Multiplayer menus (spy on player, etc.) are now greyed out in GTK+ client | |
when in single-player mode | |
t@@ -12,7 +17,7 @@ cvs | |
- "make install" installs dopewars as group "wheel" if "games" is | |
unavailable | |
-1.5.0-beta1 08-04-2001 | |
+1.5.0beta1 08-04-2001 | |
- Completely rewritten fighting code | |
- Internationalization (i18n) support | |
- Tense and case-sensitive translated strings handled via. dpg_ analogues | |
diff --git a/src/gtk_client.c b/src/gtk_client.c | |
t@@ -571,7 +571,7 @@ void PrintMessage(char *text) { | |
while (*text=='\n') text++; | |
gtk_editable_insert_text(messages,text,strlen(text),&EditPos); | |
if (text[strlen(text)-1]!='\n') { | |
- gtk_editable_insert_text(messages,cr,1,&EditPos); | |
+ gtk_editable_insert_text(messages,cr,strlen(cr),&EditPos); | |
} | |
gtk_text_thaw(GTK_TEXT(messages)); | |
gtk_editable_set_position(messages,EditPos); | |
diff --git a/src/gtkport.c b/src/gtkport.c | |
t@@ -89,6 +89,7 @@ static void gtk_container_destroy(GtkWidget *widget); | |
static void gtk_container_size_request(GtkWidget *widget, | |
GtkRequisition *requisition); | |
static void gtk_container_set_size(GtkWidget *widget,GtkAllocation *allocation… | |
+static void gtk_container_show_all(GtkWidget *widget,gboolean hWndOnly); | |
static void gtk_window_size_request(GtkWidget *widget, | |
GtkRequisition *requisition); | |
static void gtk_window_set_size(GtkWidget *widget,GtkAllocation *allocation); | |
t@@ -139,7 +140,6 @@ static void gtk_clist_realize(GtkWidget *widget); | |
static void gtk_clist_show(GtkWidget *widget); | |
static void gtk_clist_hide(GtkWidget *widget); | |
static void gtk_clist_draw_row(GtkCList *clist,LPDRAWITEMSTRUCT lpdis); | |
-static void gtk_container_show_all(GtkWidget *widget,gboolean hWndOnly); | |
static void gtk_box_show_all(GtkWidget *widget,gboolean hWndOnly); | |
static void gtk_table_show_all(GtkWidget *widget,gboolean hWndOnly); | |
static void gtk_widget_show_all_full(GtkWidget *widget,gboolean hWndOnly); | |
t@@ -166,6 +166,9 @@ static void gtk_marshal_VOID__BOOL(GtkObject *object,GSLis… | |
static void gtk_marshal_VOID__GPOIN(GtkObject *object,GSList *actions, | |
GtkSignalFunc default_action, | |
va_list args); | |
+static void gtk_marshal_VOID__GINT(GtkObject *object,GSList *actions, | |
+ GtkSignalFunc default_action, | |
+ va_list args); | |
static void gtk_menu_bar_realize(GtkWidget *widget); | |
static void gtk_menu_item_realize(GtkWidget *widget); | |
static void gtk_menu_item_enable(GtkWidget *widget); | |
t@@ -561,7 +564,7 @@ static GtkSignalType GtkCListSignals[] = { | |
{ "size_request",gtk_marshal_VOID__GPOIN,gtk_clist_size_request }, | |
{ "set_size",gtk_marshal_VOID__GPOIN,gtk_clist_set_size }, | |
{ "realize",gtk_marshal_VOID__VOID,gtk_clist_realize }, | |
- { "click-column",gtk_marshal_VOID__GPOIN,NULL }, | |
+ { "click-column",gtk_marshal_VOID__GINT,NULL }, | |
{ "show",gtk_marshal_VOID__VOID,gtk_clist_show }, | |
{ "hide",gtk_marshal_VOID__VOID,gtk_clist_hide }, | |
{ "",NULL,NULL } | |
t@@ -634,7 +637,7 @@ static GSList *GtkTimeouts=NULL; | |
static HWND TopLevel=NULL; | |
long AsyncSocketError=0; | |
-static WNDPROC wpOrigEntryProc; | |
+static WNDPROC wpOrigEntryProc,wpOrigTextProc; | |
static void gtk_set_default_font(HWND hWnd) { | |
SendMessage(hWnd,WM_SETFONT,(WPARAM)hFont,MAKELPARAM(FALSE,0)); | |
t@@ -680,11 +683,54 @@ static void DispatchTimeoutEvent(UINT id) { | |
} | |
} | |
+static void UpdatePanedGhostRect(GtkPaned *paned,RECT *OldRect,RECT *NewRect, | |
+ gint x,gint y) { | |
+ HWND hWnd,parent; | |
+ RECT rect,clrect; | |
+ POINT MouseCoord; | |
+ HDC hDC; | |
+ GtkWidget *widget=GTK_WIDGET(paned); | |
+ | |
+ if (!OldRect && !NewRect) return; | |
+ parent=gtk_get_parent_hwnd(widget); | |
+ hWnd=widget->hWnd; | |
+ if (!parent || !hWnd) return; | |
+ | |
+ MouseCoord.x=x; | |
+ MouseCoord.y=y; | |
+ MapWindowPoints(hWnd,parent,&MouseCoord,1); | |
+ | |
+ rect.left=paned->true_alloc.x; | |
+ rect.top=paned->true_alloc.y; | |
+ GetClientRect(hWnd,&clrect); | |
+ if (clrect.right > clrect.bottom) { | |
+ rect.right=paned->true_alloc.x+paned->true_alloc.width; | |
+ rect.bottom=MouseCoord.y; | |
+ } else { | |
+ rect.bottom=paned->true_alloc.y+paned->true_alloc.height; | |
+ rect.right=MouseCoord.x; | |
+ } | |
+ | |
+ if (OldRect && NewRect && OldRect->right==rect.right && | |
+ OldRect->bottom==rect.bottom) return; | |
+ | |
+ hDC=GetDC(parent); | |
+ | |
+ if (OldRect) DrawFocusRect(hDC,OldRect); | |
+ if (NewRect) { | |
+ CopyRect(NewRect,&rect); | |
+ DrawFocusRect(hDC,NewRect); | |
+ } | |
+ ReleaseDC(parent,hDC); | |
+} | |
+ | |
LRESULT CALLBACK GtkPanedProc(HWND hwnd,UINT msg,UINT wParam,LONG lParam) { | |
PAINTSTRUCT ps; | |
HPEN oldpen,dkpen,ltpen; | |
RECT rect; | |
+ static RECT GhostRect; | |
HDC hDC; | |
+ HWND parent; | |
gint newpos; | |
GtkPaned *paned; | |
paned=GTK_PANED(GetWindowLong(hwnd,GWL_USERDATA)); | |
t@@ -724,14 +770,20 @@ LRESULT CALLBACK GtkPanedProc(HWND hwnd,UINT msg,UINT wP… | |
if (!paned) break; | |
SetCapture(hwnd); | |
paned->Tracking=TRUE; | |
+ UpdatePanedGhostRect(paned,NULL,&GhostRect, | |
+ LOWORD(lParam),HIWORD(lParam)); | |
return TRUE; | |
case WM_MOUSEMOVE: | |
if (!paned||!paned->Tracking) break; | |
+ UpdatePanedGhostRect(paned,&GhostRect,&GhostRect, | |
+ LOWORD(lParam),HIWORD(lParam)); | |
return TRUE; | |
case WM_LBUTTONUP: | |
if (!paned||!paned->Tracking) break; | |
ReleaseCapture(); | |
paned->Tracking=FALSE; | |
+ UpdatePanedGhostRect(paned,&GhostRect,NULL, | |
+ LOWORD(lParam),HIWORD(lParam)); | |
GetClientRect(hwnd,&rect); | |
if (rect.right > rect.bottom) { | |
newpos=((gint16)HIWORD(lParam)+GTK_WIDGET(paned)->allocation.y- | |
t@@ -872,11 +924,16 @@ LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,UINT wPa… | |
phdr=(HD_NOTIFY FAR *)lParam; | |
nmhdr=(NMHDR *)lParam; | |
if (!nmhdr) break; | |
- if (nmhdr->code==HDN_ITEMCHANGED) { | |
+ if (nmhdr->code==HDN_ENDTRACK) { | |
gtk_clist_set_column_width_full( | |
GTK_CLIST(GetWindowLong(nmhdr->hwndFrom,GWL_USERDATA)), | |
phdr->iItem,phdr->pitem->cxy,FALSE); | |
return FALSE; | |
+ } else if (nmhdr->code==HDN_ITEMCLICK) { | |
+ gtk_signal_emit( | |
+ GTK_OBJECT(GetWindowLong(nmhdr->hwndFrom,GWL_USERDATA)), | |
+ "click-column",(gint)phdr->iItem); | |
+ return FALSE; | |
} else if (nmhdr->code==TCN_SELCHANGE) { | |
gtk_notebook_set_page( | |
GTK_NOTEBOOK(GetWindowLong(nmhdr->hwndFrom,GWL_USERDATA)), | |
t@@ -909,6 +966,18 @@ LRESULT APIENTRY EntryWndProc(HWND hwnd,UINT msg,WPARAM w… | |
return CallWindowProc(wpOrigEntryProc,hwnd,msg,wParam,lParam); | |
} | |
+LRESULT APIENTRY TextWndProc(HWND hwnd,UINT msg,WPARAM wParam, | |
+ LPARAM lParam) { | |
+ GtkWidget *widget; | |
+ if (msg==WM_GETDLGCODE) { | |
+ widget=GTK_WIDGET(GetWindowLong(hwnd,GWL_USERDATA)); | |
+ if (!GTK_EDITABLE(widget)->is_editable) { | |
+ return DLGC_HASSETSEL|DLGC_WANTARROWS; | |
+ } | |
+ } | |
+ return CallWindowProc(wpOrigTextProc,hwnd,msg,wParam,lParam); | |
+} | |
+ | |
void win32_init(HINSTANCE hInstance,HINSTANCE hPrevInstance) { | |
WNDCLASS wc; | |
hInst=hInstance; | |
t@@ -1558,26 +1627,28 @@ void gtk_editable_insert_text(GtkEditable *editable,co… | |
GtkWidget *widget=GTK_WIDGET(editable); | |
HWND hWnd; | |
gint i; | |
+ GString *newstr; | |
gtk_editable_sync_text(editable); | |
- g_string_insert(editable->text,*position,new_text); | |
- for (i=*position;i<*position+strlen(new_text);i++) { | |
- if (editable->text->str[i]=='\r' && | |
- editable->text->str[i+1]=='\n') { | |
- i++; | |
- } else if (editable->text->str[i]=='\n') { | |
- g_string_insert_c(editable->text,i,'\r'); | |
- i++; | |
- (*position)++; | |
+ | |
+ /* Convert Unix-style lone '\n' to Windows-style '\r\n' */ | |
+ newstr=g_string_new(""); | |
+ for (i=0;i<new_text_length && new_text[i];i++) { | |
+ if (new_text[i]=='\n' && (i==0 || new_text[i-1]!='\r')) { | |
+ g_string_append_c(newstr,'\r'); | |
} | |
+ g_string_append_c(newstr,new_text[i]); | |
} | |
+ g_string_insert(editable->text,*position,newstr->str); | |
hWnd=widget->hWnd; | |
if (hWnd) { | |
- SendMessage(hWnd,WM_SETTEXT,0,(LPARAM)editable->text->str); | |
- *position+=strlen(new_text); | |
+ SendMessage(hWnd,EM_SETSEL,(WPARAM)*position,(LPARAM)*position); | |
+ SendMessage(hWnd,EM_REPLACESEL,(WPARAM)FALSE,(LPARAM)newstr->str); | |
+ *position+=newstr->len; | |
gtk_editable_set_position(editable,*position); | |
} | |
+ g_string_free(newstr,TRUE); | |
} | |
void gtk_editable_delete_text(GtkEditable *editable, | |
t@@ -1623,9 +1694,8 @@ void gtk_editable_set_position(GtkEditable *editable,gin… | |
HWND hWnd; | |
if (!GTK_WIDGET_REALIZED(widget)) return; | |
hWnd=widget->hWnd; | |
- SendMessage(hWnd,EM_SETSEL,(WPARAM)-1,(LPARAM)position); | |
+ SendMessage(hWnd,EM_SETSEL,(WPARAM)position,(LPARAM)position); | |
SendMessage(hWnd,EM_SCROLLCARET,0,0); | |
- SendMessage(hWnd,EM_LINESCROLL,0,(LPARAM)1000); | |
} | |
gint gtk_editable_get_position(GtkEditable *editable) { | |
t@@ -1988,13 +2058,21 @@ void gtk_entry_realize(GtkWidget *widget) { | |
void gtk_text_realize(GtkWidget *widget) { | |
HWND Parent; | |
+ gboolean editable; | |
+ | |
Parent=gtk_get_parent_hwnd(widget); | |
+ editable=GTK_EDITABLE(widget)->is_editable; | |
GTK_WIDGET_SET_FLAGS(widget,GTK_CAN_FOCUS); | |
widget->hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"EDIT","", | |
- WS_CHILD|WS_TABSTOP| | |
+ WS_CHILD|(editable ? WS_TABSTOP : 0)| | |
ES_MULTILINE|ES_WANTRETURN|WS_VSCROLL| | |
(GTK_TEXT(widget)->word_wrap ? 0 : ES_AUTOHSCROLL), | |
0,0,0,0,Parent,NULL,hInst,NULL); | |
+/* Subclass the window (we assume that all multiline edit boxes have the same | |
+ window procedure) */ | |
+ wpOrigTextProc = (WNDPROC) SetWindowLong(widget->hWnd, | |
+ GWL_WNDPROC, | |
+ (LONG)TextWndProc); | |
gtk_set_default_font(widget->hWnd); | |
gtk_editable_set_editable(GTK_EDITABLE(widget), | |
GTK_EDITABLE(widget)->is_editable); | |
t@@ -2125,7 +2203,7 @@ void gtk_clist_realize(GtkWidget *widget) { | |
/* g_print("Header %p, size %d\n",header,wp.cy);*/ | |
widget->hWnd = CreateWindowEx(WS_EX_CLIENTEDGE,"LISTBOX","", | |
WS_CHILD|WS_TABSTOP|LBS_DISABLENOSCROLL| | |
- WS_VSCROLL|LBS_USETABSTOPS| | |
+ WS_VSCROLL| | |
LBS_OWNERDRAWFIXED|LBS_NOTIFY, | |
0,0,0,0,Parent,NULL,hInst,NULL); | |
gtk_set_default_font(widget->hWnd); | |
t@@ -2140,12 +2218,14 @@ void gtk_clist_realize(GtkWidget *widget) { | |
hdi.mask = HDI_TEXT|HDI_FORMAT|HDI_WIDTH; | |
hdi.pszText=clist->cols[i].title; | |
if (hdi.pszText) { | |
- hdi.cxy=clist->cols[i].width; | |
+ if (i==clist->ncols-1) hdi.cxy=9000; | |
+ else hdi.cxy=clist->cols[i].width; | |
hdi.cchTextMax=strlen(hdi.pszText); | |
hdi.fmt = HDF_LEFT|HDF_STRING; | |
SendMessage(header,HDM_INSERTITEM,i+1,(LPARAM)&hdi); | |
} | |
} | |
+ | |
} | |
void gtk_clist_show(GtkWidget *widget) { | |
t@@ -2189,6 +2269,7 @@ void gtk_clist_draw_row(GtkCList *clist,LPDRAWITEMSTRUCT… | |
rcCol.right=CurrentX-LISTITEMHPACK; | |
if (rcCol.left > lpdis->rcItem.right) rcCol.left=lpdis->rcItem.right; | |
if (rcCol.right > lpdis->rcItem.right) rcCol.right=lpdis->rcItem.righ… | |
+ if (i==clist->ncols-1) rcCol.right=lpdis->rcItem.right; | |
if (row->text[i]) DrawText(lpdis->hDC,row->text[i],-1,&rcCol, | |
DT_LEFT|DT_SINGLELINE|DT_VCENTER); | |
} | |
t@@ -2260,7 +2341,7 @@ gint gtk_clist_insert(GtkCList *clist,gint row,gchar *te… | |
if (GTK_WIDGET_REALIZED(widget)) { | |
hWnd=widget->hWnd; | |
- SendMessage(hWnd,LB_INSERTSTRING,(WPARAM)row,(LPARAM)new_row->data); | |
+ SendMessage(hWnd,LB_INSERTSTRING,(WPARAM)row,(LPARAM)NULL); | |
} | |
return row; | |
t@@ -2344,6 +2425,7 @@ void gtk_clist_set_column_width_full(GtkCList *clist,gin… | |
header=clist->header; | |
if (ResizeHeader && header) { | |
hdi.mask=HDI_WIDTH; | |
+ if (column==clist->ncols-1) width=9000; | |
hdi.cxy=width; | |
if (SendMessage(header,HDM_GETITEM,(WPARAM)column,(LPARAM)&hdi) && | |
hdi.cxy!=width) { | |
t@@ -2921,6 +3003,24 @@ void gtk_marshal_VOID__VOID(GtkObject *object,GSList *a… | |
if (default_action) (*default_action)(object); | |
} | |
+void gtk_marshal_VOID__GINT(GtkObject *object,GSList *actions, | |
+ GtkSignalFunc default_action, | |
+ va_list args) { | |
+ gint arg1; | |
+ GtkSignal *signal; | |
+ | |
+ arg1=va_arg(args,gint); | |
+ | |
+ while (actions) { | |
+ signal=(GtkSignal*)actions->data; | |
+ if (signal->slot_object) { | |
+ (*signal->func)(signal->slot_object,arg1); | |
+ } else (*signal->func)(object,arg1,signal->func_data); | |
+ actions=g_slist_next(actions); | |
+ } | |
+ if (default_action) (*default_action)(object,arg1); | |
+} | |
+ | |
void gtk_marshal_VOID__GPOIN(GtkObject *object,GSList *actions, | |
GtkSignalFunc default_action, | |
va_list args) { | |
t@@ -3923,7 +4023,51 @@ void gtk_text_freeze(GtkText *text) { | |
void gtk_text_thaw(GtkText *text) { | |
} | |
+static GtkCList *sorting_clist; | |
+static gint gtk_clist_sort_func(gconstpointer a,gconstpointer b) { | |
+ return (*sorting_clist->cmp_func)(sorting_clist,a,b); | |
+} | |
+ | |
void gtk_clist_sort(GtkCList *clist) { | |
+ HWND hWnd; | |
+ gint rowind; | |
+ GList *sel; | |
+ GSList *rowpt; | |
+ | |
+ sorting_clist=clist; | |
+ if (clist && clist->cmp_func && clist->rows) { | |
+/* Since the order of the list may change, we need to change the selection | |
+ as well. Do this by converting the row indices into GSList pointers (which | |
+ are invariant to the sort) and then convert back afterwards */ | |
+ for (sel=clist->selection;sel;sel=g_list_next(sel)) { | |
+ rowind=GPOINTER_TO_INT(sel->data); | |
+ sel->data=(gpointer)g_slist_nth(clist->rows,rowind); | |
+ } | |
+ clist->rows=g_slist_sort(clist->rows,gtk_clist_sort_func); | |
+ for (sel=clist->selection;sel;sel=g_list_next(sel)) { | |
+ rowpt=(GSList *)(sel->data); | |
+ sel->data=GINT_TO_POINTER(g_slist_position(clist->rows,rowpt)); | |
+ } | |
+ if (GTK_WIDGET_REALIZED(GTK_WIDGET(clist))) { | |
+ hWnd=GTK_WIDGET(clist)->hWnd; | |
+ if (clist->mode==GTK_SELECTION_SINGLE) { | |
+ sel=clist->selection; | |
+ if (sel) rowind=GPOINTER_TO_INT(sel->data); | |
+ else rowind=-1; | |
+ SendMessage(hWnd,LB_SETCURSEL,(WPARAM)rowind,0); | |
+ } else { | |
+ for (rowind=0;rowind<g_slist_length(clist->rows);rowind++) { | |
+ SendMessage(hWnd,LB_SETSEL,(WPARAM)FALSE,(LPARAM)rowind); | |
+ } | |
+ for (sel=clist->selection;sel;sel=g_list_next(sel)) { | |
+ rowind=GPOINTER_TO_INT(sel->data); | |
+ SendMessage(hWnd,LB_SETSEL,(WPARAM)TRUE,(LPARAM)rowind); | |
+ } | |
+ } | |
+ InvalidateRect(hWnd,NULL,FALSE); | |
+ UpdateWindow(hWnd); | |
+ } | |
+ } | |
} | |
void gtk_clist_freeze(GtkCList *clist) { | |
t@@ -4126,6 +4270,7 @@ void gtk_clist_moveto(GtkCList *clist,gint row,gint colu… | |
} | |
void gtk_clist_set_compare_func(GtkCList *clist,GtkCListCompareFunc cmp_func) { | |
+ if (clist) clist->cmp_func = cmp_func; | |
} | |
void gtk_clist_set_column_auto_resize(GtkCList *clist,gint column, | |
diff --git a/src/gtkport.h b/src/gtkport.h | |
t@@ -355,6 +355,7 @@ struct _GtkCList { | |
GtkCListColumn *cols; | |
GList *selection; | |
GtkSelectionMode mode; | |
+ GtkCListCompareFunc cmp_func; | |
gint auto_sort : 1; | |
}; | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -1082,7 +1082,9 @@ int InitHighScoreFile() { | |
if (ScoreFP) return 0; /* If already opened, then we're done */ | |
- ScoreFP=fopen(HiScoreFile,"a+"); | |
+ /* Win32 gets upset if we use "a+" so we use this nasty hack instead */ | |
+ ScoreFP=fopen(HiScoreFile,"r+"); | |
+ if (!ScoreFP) ScoreFP=fopen(HiScoreFile,"w+"); | |
#ifndef CYGWIN | |
if (setregid(getgid(),getgid())!=0) perror("setregid"); | |
t@@ -1121,6 +1123,7 @@ int HighScoreWrite(struct HISCORE *MultiScore,struct HIS… | |
HighScoreTypeWrite(AntiqueScore,ScoreFP); | |
HighScoreTypeWrite(MultiScore,ScoreFP); | |
ReleaseLock(ScoreFP); | |
+ fflush(ScoreFP); | |
} else return 0; | |
return 1; | |
} |