/** * * xviewer.c - (c) 1994 Copyright by John R. Punin * * ASHE * * This file has the routines to reload the HTML documents * * Create new frames of ASHE and Local Navigation * * John R. Punin Jul-24- 1994 * */ #include "xhtml.h" #include "xviewer.h" #include "xfile.h" #include "xbitmap.h" #include "xform.h" #include "xurl.h" extern int tableSupportEnabled; MenuItem option_menu[] = { { "Load Images", &xmToggleButtonWidgetClass, 'L', NULL,NULL, toggle_images, 0, NULL}, { "Table Support", &xmToggleButtonWidgetClass, 'T', NULL,NULL, toggle_tables, 0, NULL}, NULL,}; /* NAME : ViewerButtonCallBack PARAMETERS : Not used RETURN : void DESCRIPTION : This Routine creates a new window to browse the html document */ extern HTML_LIST *head_html; extern HTML_LIST *tail_html; extern MyAppResType myAppRes; Widget html_help; Widget CreateHTMLwidget(Widget w,HTMLED *he) { Widget html_text,view; String tstring; int narg; Arg arglist[MAXARGS]; /* * Create HTML widget to browse Hypertext documents. */ narg = 0; XtSetArg(arglist[narg],XmNwidth ,550 ); narg++; XtSetArg(arglist[narg],XmNheight ,300 ); narg++; html_text = XtVaCreateManagedWidget("texthtml", htmlWidgetClass,w,NULL); XtSetValues(html_text,arglist,narg); view = XtNameToWidget(html_text,"View"); if(view) XtAddEventHandler(view, KeyPressMask, False,keypress_handler,NULL); XtManageChild(html_text); tstring = XmTextGetString(he->textarea); XtVaSetValues(html_text,WbNresolveImageFunction,ImageResolve, XmNuserData,(XtPointer)he,NULL); HTMLSetText(html_text,tstring,NULL,NULL,0,NULL,NULL); XtFree(tstring); return(html_text); } /* Image resolution function. */ ImageInfo * ImageResolve (Widget w, char *src) { int i, cnt=256; unsigned char *data; /* unsigned char *bg_map; unsigned char *bgptr; unsigned char *ptr;*/ int width, height; /* int Used[256]; int widthbyheight = 0;*/ XColor colrs[256]; /* Pixel fg1, bg1; Pixmap pixmap;*/ int bg, bg_red, bg_green, bg_blue; Widget view; ImageInfo *img_data; char *abs_src; HTMLED *he=NULL; XtVaGetValues(w,XmNuserData,&he,NULL); if(he->load_image == TRUE) /* No load Images */ return NULL; /* fprintf(stderr," (1) widget name: %s\n",XtName(w)); *//* texthtml */ view = XtNameToWidget(w,"View"); /* XtVaGetValues(view,XmNforeground,&fg1, XmNbackground,&bg1, NULL); pixmap=XmGetPixmap(XtScreen(view),"/dept/cs/sysprog/oldstuff/thumbs_up", fg1, bg1); XtVaCreateManagedWidget("Up", xmLabelWidgetClass,view, XmNlabelType, XmPIXMAP, XmNlabelPixmap,pixmap, NULL); XtVaCreateManagedWidget("** Label **",xmLabelWidgetClass, view, NULL); */ /* printf ("[ImageResolve] I'm entering, src '%s'\n", src); */ /* binding src to the file name */ if(src[0]!='/') { char *directory; abs_src=getfile_href(src,he,&directory); if (directory) /*Memory Leaking */ XtFree(directory); } else abs_src = strdup(src); data = ReadBitmap(abs_src, &width, &height, colrs, &bg, view); /* if we have a transparent background, prepare for it */ if ((bg >= 0)&&(data != NULL)) { unsigned long bg_pixel; XColor tmpcolr; XtVaGetValues(view, XtNbackground, &bg_pixel, NULL); tmpcolr.pixel = bg_pixel; /* return the RGB associated with the bg_pixel */ XQueryColor(XtDisplay(view), DefaultColormap(XtDisplay(view), DefaultScreen(XtDisplay(view))), &tmpcolr); bg_red = colrs[bg].red = tmpcolr.red; bg_green = colrs[bg].green = tmpcolr.green; bg_blue = colrs[bg].blue = tmpcolr.blue; colrs[bg].flags = DoRed|DoGreen|DoBlue; /*bg_map = (unsigned char *)malloc(width * height);*/ } if(data == NULL) return NULL; img_data = (ImageInfo *)malloc(sizeof(ImageInfo)); img_data->width = width; img_data->height = height; img_data->image_data = data; img_data->image = (Pixmap)NULL; img_data->internal = 0; /* widthbyheight = img_data->width * img_data->height; for (i=0; i < 256; i++) { Used[i] = 0; } cnt = 1; bgptr = bg_map; ptr = img_data->image_data; for (i=0; i < widthbyheight; i++) { if (Used[(int)*ptr] == 0) { Used[(int)*ptr] = cnt; cnt++; } if (bg >= 0) { if (*ptr == bg) { *bgptr = (unsigned char)1; } else { *bgptr = (unsigned char)0; } bgptr++; } ptr++; } cnt--; */ /* * If the image has too many colors, apply a median cut algorithm to * reduce the color usage, and then reprocess it. * Don't cut colors for direct mapped visuals like TrueColor. */ /* if ((cnt > Rdata.colors_per_inlined_image)&&(Vclass != TrueColor)) { MedianCut(img_data->image_data, &img_data->width, &img_data->height, colrs, 256, Rdata.colors_per_inlined_image); for (i=0; i < 256; i++) Used[i] = 0; cnt = 1; ptr = img_data->image_data; for (i=0; i < widthbyheight; i++) { if (Used[(int)*ptr] == 0) { Used[(int)*ptr] = cnt; cnt++; } ptr++; } cnt--; ** if we had a transparent bg, MedianCut used it. Get a new one ** if (bg >= 0) { cnt++; bg = 256; } } */ img_data->num_colors = cnt; img_data->reds = (int *)malloc(sizeof(int) * cnt); img_data->greens = (int *)malloc(sizeof(int) * cnt); img_data->blues = (int *)malloc(sizeof(int) * cnt); for (i=0; i < 256; i++) { /* int indx; if (Used[i] != 0) { indx = Used[i] - 1; img_data->reds[indx] = colrs[i].red; img_data->greens[indx] = colrs[i].green; img_data->blues[indx] = colrs[i].blue; if ((bg >= 0)&&(i == bg)) { img_data->reds[indx] = bg_red; img_data->greens[indx] = bg_green; img_data->blues[indx] = bg_blue; } } */ img_data->reds[i] = colrs[i].red; img_data->greens[i] = colrs[i].green; img_data->blues[i] = colrs[i].blue; } free(abs_src); return img_data; } void Reload_HTML( Widget w, XtPointer client_data, XtPointer call_data) { HTMLED *he = (HTMLED *)client_data; String tstring,title; int vr,ssr, ir,pir; Widget verbar=XtNameToWidget(he->html_text,"Vbar"); if(verbar) { XmScrollBarGetValues(verbar,&vr,&ssr,&ir,&pir); /* printf("Info is vr=%d,ssr=%d,ir=%d,pir=%d\n",vr,ssr,ir,pir);*/ } tstring = XmTextGetString(he->textarea); tableSupportEnabled = he->table_support; /* Support for Tables */ HTMLSetText(he->html_text,tstring,NULL,NULL,0,he->anchor_target,NULL); if(verbar) XmScrollBarSetValues(verbar,vr,ssr,ir,pir,True); title = get_title(he->html_text); if(title!=NULL) Set_label(he->title_output,title); else Set_label(he->title_output,""); XmProcessTraversal(he->textarea,XmTRAVERSE_CURRENT); XtFree(tstring); XtFree(title); } void CreateNewFrame(Widget w,HTMLED *he) { HTMLED *nhe; Widget parent = he->textarea; Widget shell_frame; shell_frame = XtVaCreatePopupShell("sframe", topLevelShellWidgetClass, parent, NULL); tableSupportEnabled = FALSE; /* Support for Tables */ nhe = create_rest_widgets(shell_frame,he); Insert_html_frame(nhe); /* Print_Frames();*/ nhe->shell = shell_frame; XtPopup(shell_frame, XtGrabNone); } void CloseFrame(Widget w, HTMLED *he) { Widget wshell = he->shell; char buf[BUFSIZ]; int ask; if(strcmp(XtName(wshell),"xhtml")) { if(he->modified_file) { char *fname = he->Name_File; char *question=XtMalloc(strlen(fname)+50); sprintf(question, "File %s has been modified. \n Do you want to save it?",fname); if((ask = AskUser(he->textarea, question))==YES) { if(save_file_ok(he)) { sprintf(buf,"This file %s can not be saved",fname); printf("%s",buf); Set_label(he->text_output,buf); XtFree(question); return; } } else if(ask == CANCEL) { XtFree(question); return; } XtFree(question); } Delete_html_frame(he); /* Print_Frames();*/ XtFree((char *)he); XtPopdown(wshell); } else Set_label(he->text_output,"The main window xhtml can not be closed"); } void anchor_call(Widget w, XtPointer client_data, XtPointer call_data) { HTMLED *he = (HTMLED *)client_data; WbAnchorCallbackData *ele_ref=(WbAnchorCallbackData *)call_data; char *buf; char *href=NULL,*name=NULL; struct stat statbuf; /* information on a file */ /* printf("text is %s\n",ele_ref->text); printf("href is %s\n",ele_ref->href); printf ("id is %d \n",ele_ref->element_id); printf("anchor is called\n"); */ XtFree(he->href); he->href=NULL; strip_href(ele_ref->href,&href,&name); /* printf("href is %s, name is %s\n",href,name);*/ if(name!=NULL) { XtFree(he->anchor_target); he->anchor_target = XtMalloc(strlen(name)+1); strcpy(he->anchor_target,name); XtFree(name); } if((href!=NULL)&&(href[0]!='\0')) { char *directory = getdirectory(he->Name_File); int isfile; char *href_abs= NULL; XtFree(he->href); if(directory) { href_abs = binding_relative_url(href,he,directory,&isfile); XtFree(directory); XtFree(href); } he->href = href_abs; if(stat(he->href, &statbuf) == 0) { if(S_ISDIR(statbuf.st_mode)) { buf = XtMalloc(strlen(he->href)+20); sprintf(buf,"%s is a directory",he->href); Set_label(he->text_output,buf); XtFree(buf); XtFree(he->href); he->href = NULL; return; } } if(open(he->href,O_RDONLY,0)!=-1) CreateNewFrame(w,he); else { buf = XtMalloc(strlen(he->href)+20); sprintf(buf,"Can't open to %s",he->href); Set_label(he->text_output,buf); XtFree(he->href); he->href = NULL; XtFree(buf); } } else { if(he->anchor_target!=NULL) Reload_HTML(w,(XtPointer)he,NULL); } } char * getfile_href(char *nhref,HTMLED *he,char **directory) { char *fname = he->Name_File; int len=strlen(fname); char *path=NULL; char *href = NULL; int i,j; if(len!=0) { for(i=len-1;i>=0;i--) if(fname[i]=='/') break; if(i!=0) { path = XtMalloc(len+2); for(j=0;j<=i;j++) path[j]=fname[j]; path[j]='\0'; href=XtMalloc(i+strlen(nhref)+5); strcpy(href,path); strcat(href,nhref); } } *directory = path; return(href); } char * get_title(Widget whtml) { String buffer=NULL; char *title=NULL; /* HTMLWidget hw = (HTMLWidget) whtml; char *wtitle = hw->html.title; if(wtitle!=NULL) { title = XtMalloc(strlen(wtitle)); strcpy(title,wtitle); } */ XtVaGetValues(whtml,WbNtitleText,&buffer,NULL); if(buffer != NULL) { title = XtMalloc(strlen(buffer)+2); strcpy(title,buffer); } /*XtFree(buffer);*/ return(title); } void Insert_html_frame(HTMLED *he) { HTML_LIST *htemp = (HTML_LIST *)XtMalloc(sizeof(HTML_LIST)); htemp->fr = he; htemp->next = head_html->next; head_html->next = htemp; } void Delete_html_frame(HTMLED *he) { HTML_LIST *htemp,*hfound; for(htemp = head_html;htemp->next != NULL; htemp = htemp->next) if(htemp->next->fr == he) break; if(htemp->next) { hfound = htemp->next; htemp->next = hfound->next; XtFree((XtPointer)hfound); } else printf("Something is wrong. Your frame was not deleted from memory\n"); } void Print_Frames(void) { HTML_LIST *htemp; int i=0; printf("\n Frame List :\n"); for(htemp = head_html->next; htemp != tail_html; htemp = htemp->next) printf("Fr %d :%s\n",i++,htemp->fr->Name_File); } void Exit_ASHE(Widget w) { save_unmodified_files(w); exit_dialog(w); } void exit_dialog(Widget w) { Widget dialog; XmString text,ok_str,cancel_str; char *msg = "Do you really want to exit? \n"; dialog = XmCreateWarningDialog(w,"warning",NULL,0); text = XmStringCreateLtoR(msg,XmFONTLIST_DEFAULT_TAG); ok_str = XmStringCreateLocalized("Yes"); cancel_str = XmStringCreateLocalized("No"); XtVaSetValues(dialog, XmNmessageString,text, XmNokLabelString,ok_str, XmNcancelLabelString,cancel_str, NULL); /* Nor help neither text is available.... */ XtUnmanageChild(XmMessageBoxGetChild(dialog,XmDIALOG_HELP_BUTTON)); XtAddCallback(dialog,XmNokCallback,(XtCallbackProc)exit,NULL); XmStringFree(text); XmStringFree(ok_str); XmStringFree(cancel_str); XtManageChild(dialog); XtPopup(XtParent(dialog),XtGrabNone); } int ask_save_file(Widget w,HTMLED *he) { int ask; char *fname = he->Name_File; char *question=XtMalloc(strlen(fname)+100); char buf[BUFSIZ]; sprintf(question, "File %s has been modified. \n Do you want to save it?",fname); if((ask = AskUser(w, question))==YES) { if(save_file_ok(he)) { sprintf(buf,"This file %s can not be saved",he->Name_File); printf("%s",buf); Set_label(he->text_output,buf); XtFree(question); return 1; } } else if(ask == CANCEL) { XtFree(question); return 1; } XtFree(question); return 0; } void save_unmodified_files(Widget w) { HTML_LIST *htemp; HTMLED *he; for(htemp = head_html->next; htemp != tail_html; htemp = htemp->next) { he=htemp->fr; if(he->modified_file) { if(ask_save_file(w,he)) return; } } } void Create_Shell_Help(Widget w, XtPointer client_data, XtPointer call_data) { /*HTMLED *he = (HTMLED *)client_data;*/ HTMLED *he=NULL; static Widget shell_help = NULL; Widget parent = XtParent(w); Widget workarea,dismiss,frame; int item_no = (int)client_data; char *anchor=NULL; if(item_no == 0) { anchor = XtMalloc(8); strcpy(anchor,"ASHE"); } if(item_no == 1) { anchor = XtMalloc(15); strcpy(anchor,"Key_Bindings"); } if(item_no == 2) { anchor = XtMalloc(15); strcpy(anchor,"charac_ref"); } XtVaGetValues(parent,XmNuserData,&he,NULL); if(!shell_help) { Widget view; shell_help = XtVaCreatePopupShell("help_frame", topLevelShellWidgetClass,he->textarea, NULL); workarea = XmCreateForm(shell_help, "workhtml", NULL, 0); frame = XtVaCreateManagedWidget("frame_html",xmFrameWidgetClass,workarea, XmNshadowType, XmSHADOW_ETCHED_IN, NULL); html_help = CreateHTMLwidget_help(frame,he,anchor); view = XtNameToWidget(html_help,"View"); if(view) XtAddEventHandler(view, KeyPressMask, False,keypress_handler,NULL); dismiss = XmCreatePushButton(workarea,"dismiss",NULL,0); XtAddCallback(dismiss,XmNactivateCallback,popdown_help,NULL); XtAddCallback(html_help,WbNanchorCallback,anchor_help,he); XtVaSetValues(frame, XmNbottomAttachment, XmATTACH_FORM, XmNleftAttachment,XmATTACH_FORM, XmNrightAttachment,XmATTACH_FORM, XmNtopAttachment,XmATTACH_WIDGET, XmNtopWidget, dismiss, NULL); XtVaSetValues(dismiss,XmNtopAttachment,XmATTACH_FORM, NULL); XtManageChild(frame); XtManageChild(dismiss); XtManageChild(workarea); } else if(anchor) HTMLGotoId(html_help,HTMLAnchorToId(html_help,anchor)); XtFree(anchor); XtPopup(shell_help, XtGrabNone); } void BuildHelpMenu(Widget menubar,HTMLED *he) { XmString on_keys,on_index,on_charac,index_acc; on_index = XmStringCreateSimple("On Index..."); index_acc = XmStringCreateSimple("Ctrl-h"); on_keys = XmStringCreateSimple("On Keys..."); on_charac = XmStringCreateSimple("On Characters..."); XmVaCreateSimplePulldownMenu(menubar,"help_menu",0,Create_Shell_Help, XmVaPUSHBUTTON, on_index, 'I',"Ctrlh",index_acc, XmVaPUSHBUTTON, on_keys, 'K',"",NULL, XmVaPUSHBUTTON, on_charac, 'C',"",NULL, XmNuserData,he, NULL); XmStringFree(on_index);XmStringFree(on_keys);XmStringFree(index_acc); XmStringFree(on_charac); } Widget CreateHTMLwidget_help(Widget w,HTMLED *he,char* anchor) { Widget html_text; String tstring; int narg; Arg arglist[MAXARGS]; /* * Create HTML widget to browse Hypertext documents. */ narg = 0; XtSetArg(arglist[narg],XmNwidth ,550 ); narg++; XtSetArg(arglist[narg],XmNheight ,300 ); narg++; html_text = XtVaCreateManagedWidget("texthtml", htmlWidgetClass,w,NULL); XtSetValues(html_text,arglist,narg); XtManageChild(html_text); tstring = read_help(); HTMLSetText(html_text,tstring,NULL,NULL,0,anchor,NULL); XtFree(tstring); return(html_text); } String read_help(void) { int fd; String name = "help.html"; String fname; String mybuf; struct stat statbuf; /* information on a file */ int file_length=0; int i=0; long n; mybuf = XtMalloc(90); strcpy(mybuf, "Error in help.html. \n Please, check in your resources file the htmldir resource"); printf("Resource directory is %s\n",myAppRes.htmldir); if(myAppRes.htmldir) { fname = XtMalloc(strlen(name)+strlen(myAppRes.htmldir)+2); strcpy(fname,myAppRes.htmldir); strcat(fname,"/"); strcat(fname,name); } else fname = name; if(stat(fname, &statbuf) == 0) file_length = statbuf.st_size; /* Opening and Reading the file */ if((fd = open(fname,O_RDONLY,0)) == -1) { fprintf(stderr,"File %s does not exist\n\n",name); XtFree(fname); return mybuf; } XtFree(mybuf); mybuf = (char *)XtMalloc((unsigned)file_length+5); while((n = read(fd, mybuf, file_length)) > 0) { if(n!=file_length) fprintf(stderr,"Warning: did not read entire file!"); i++; if (i==2) fprintf(stderr,"Reading the buffer again\n"); } XtFree(fname); return(mybuf); } void popdown_help(Widget w, XtPointer client_data, XtPointer call_data) { XtPopdown(XtParent(XtParent(w))); } void anchor_help(Widget w, XtPointer client_data, XtPointer call_data) { WbAnchorCallbackData *ele_ref=(WbAnchorCallbackData *)call_data; char *href=NULL,*name=NULL; strip_href(ele_ref->href,&href,&name); if(href[0]=='\0') { if((name!=NULL)&&(name[0]!='\0')) HTMLGotoId(html_help,HTMLAnchorToId(html_help,name)); } } XtEventHandler keypress_handler(Widget w, XtPointer client_data, XEvent *event, Boolean* bool) { char mbuffer[20]; int mbufsize = 20; KeySym mkey; int charcount; XComposeStatus compose; Widget html_text = XtParent(w); Widget vbar = XtNameToWidget(html_text,"Vbar"); Widget hbar = XtNameToWidget(html_text,"Hbar"); charcount = XLookupString((XKeyEvent *)event,mbuffer,mbufsize,&mkey,&compose); /* Page up. */ if((mkey == XK_BackSpace) || (mkey == XK_Delete)) { String params[1]; params[0] = "0"; if (vbar && XtIsManaged (vbar)) { XtCallActionProc (vbar, "PageUpOrLeft", event, params, 1); } } /* Page down. */ if(mkey == XK_Tab || mkey == XK_Return || mkey == XK_space) { String params[1]; params[0] = "0"; if (vbar && XtIsManaged (vbar)) { XtCallActionProc (vbar, "PageDownOrRight", event, params, 1); } } if (mkey == XK_Down #if XlibSpecificationRelease-5 || mkey == XK_KP_Down #endif ) { String params[1]; params[0] = "0"; if (vbar && XtIsManaged (vbar)) { XtCallActionProc (vbar, "IncrementDownOrRight", event, params, 1); } } if (mkey == XK_Right #if XlibSpecificationRelease-5 || mkey == XK_KP_Right #endif ) { String params[1]; params[0] = "1"; if (hbar && XtIsManaged (hbar)) { XtCallActionProc (hbar, "IncrementDownOrRight", event, params, 1); } } if (mkey == XK_Up #if XlibSpecificationRelease-5 || mkey == XK_KP_Up #endif ) { String params[1]; params[0] = "0"; if (vbar && XtIsManaged (vbar)) { XtCallActionProc (vbar, "IncrementUpOrLeft", event, params, 1); } } if (mkey == XK_Left #if XlibSpecificationRelease-5 || mkey == XK_KP_Left #endif ) { String params[1]; params[0] = "1"; if (hbar && XtIsManaged (hbar)) { XtCallActionProc (hbar, "IncrementUpOrLeft", event, params, 1); } } } void toggle_images(Widget w,XtPointer client_data,XtPointer call_data) { XmToggleButtonCallbackStruct *cbs = (XmToggleButtonCallbackStruct *)call_data; HTMLED *he = (HTMLED *)client_data; he->load_image = cbs->set; } void toggle_tables(Widget w,XtPointer client_data,XtPointer call_data) { XmToggleButtonCallbackStruct *cbs = (XmToggleButtonCallbackStruct *)call_data; HTMLED *he = (HTMLED *)client_data; tableSupportEnabled = he->table_support = cbs->set; }